// constructors public CmsSigner () { _signer = SubjectIdentifierType.IssuerAndSerialNumber; _digest = new Oid ("1.3.14.3.2.26"); _options = X509IncludeOption.ExcludeRoot; _signed = new CryptographicAttributeObjectCollection (); _unsigned = new CryptographicAttributeObjectCollection (); _coll = new X509Certificate2Collection (); }
// only accessible from SignedPkcs7.SignerInfos internal SignerInfo (string hashName, X509Certificate2 certificate, SubjectIdentifierType type, object o, int version) { _digest = new Oid (CryptoConfig.MapNameToOID (hashName)); _certificate = certificate; _counter = new SignerInfoCollection (); _signed = new CryptographicAttributeObjectCollection (); _unsigned = new CryptographicAttributeObjectCollection (); _signer = new SubjectIdentifier (type, o); _version = version; }
public EnvelopedCms(ContentInfo contentInfo, AlgorithmIdentifier encryptionAlgorithm) { if (contentInfo == null) throw new ArgumentNullException(nameof(contentInfo)); if (encryptionAlgorithm == null) throw new ArgumentNullException(nameof(encryptionAlgorithm)); Version = 0; // It makes little sense to ask for a version before you've decoded, but since the desktop returns 0 in that case, we will too. ContentInfo = contentInfo; ContentEncryptionAlgorithm = encryptionAlgorithm; Certificates = new X509Certificate2Collection(); UnprotectedAttributes = new CryptographicAttributeObjectCollection(); _decryptorPal = null; _lastCall = LastCall.Ctor; }
public static void NonEmbeddedCertificate() { SignedCms cms = new SignedCms(); cms.Decode(SignedDocuments.RsaCapiTransfer1_NoEmbeddedCert); Assert.Equal(3, cms.Version); Assert.Equal(Oids.Pkcs7Data, cms.ContentInfo.ContentType.Value); Assert.Equal( "4D6963726F736F667420436F72706F726174696F6E", cms.ContentInfo.Content.ByteArrayToHex()); Assert.Empty(cms.Certificates); SignerInfoCollection signers = cms.SignerInfos; Assert.Single(signers); SignerInfo signer = signers[0]; Assert.Equal(3, signer.Version); Assert.Equal(SubjectIdentifierType.SubjectKeyIdentifier, signer.SignerIdentifier.Type); Assert.Equal("6B4A6B92FDED07EE0119F3674A96D1A70D2A588D", (string)signer.SignerIdentifier.Value); Assert.Equal(Oids.Sha1, signer.DigestAlgorithm.Value); CryptographicAttributeObjectCollection signedAttrs = signer.SignedAttributes; Assert.Equal(3, signedAttrs.Count); Pkcs9ContentType contentType = (Pkcs9ContentType)signedAttrs[0].Values[0]; Pkcs9SigningTime signingTime = (Pkcs9SigningTime)signedAttrs[1].Values[0]; Pkcs9MessageDigest messageDigest = (Pkcs9MessageDigest)signedAttrs[2].Values[0]; Assert.Equal(Oids.Pkcs7Data, contentType.ContentType.Value); Assert.Equal( new DateTimeOffset(2017, 11, 2, 15, 34, 4, TimeSpan.Zero), signingTime.SigningTime); Assert.Equal(DateTimeKind.Utc, signingTime.SigningTime.Kind); Assert.Empty(signer.UnsignedAttributes); Assert.Empty(signer.CounterSignerInfos); Assert.Null(signer.Certificate); #if netcoreapp Assert.Equal(Oids.Rsa, signer.SignatureAlgorithm.Value); Assert.Equal( "0EDE3870B8A80B45A21BAEC4681D059B46502E1B1AA6B8920CF50D4D837646A5" + "5559B4C05849126C655D95FF3C6C1B420E07DC42629F294EE69822FEA56F32D4" + "1B824CBB6BF809B7583C27E77B7AC58DFC925B1C60EA4A67AA84D73FC9E9191D" + "33B36645F17FD6748A2D8B12C6C384C3C734D27273386211E4518FE2B4ED0147", signer.GetSignature().ByteArrayToHex()); #endif using (SHA1 sha1 = SHA1.Create()) { Assert.Equal( sha1.ComputeHash(cms.ContentInfo.Content).ByteArrayToHex(), messageDigest.MessageDigest.ByteArrayToHex()); } // Since it's not NoSignature CheckHash will throw. Assert.Throws <CryptographicException>(() => signer.CheckHash()); // Since there's no matched certificate CheckSignature will throw. Assert.Throws <CryptographicException>(() => signer.CheckSignature(true)); // Since there are no NoSignature signers, SignedCms.CheckHash will succeed cms.CheckHash(); // Since there are no matched certificates SignedCms.CheckSignature will throw. Assert.Throws <CryptographicException>(() => cms.CheckSignature(true)); using (X509Certificate2 wrongCert = Certificates.RSAKeyTransfer1.GetCertificate()) using (X509Certificate2 rightCert = Certificates.RSAKeyTransferCapi1.GetCertificate()) { X509Certificate2Collection coll = new X509Certificate2Collection(wrongCert); // Wrong certificate, still throw. Assert.Throws <CryptographicException>(() => signer.CheckSignature(coll, true)); Assert.Throws <CryptographicException>(() => cms.CheckSignature(coll, true)); coll = new X509Certificate2Collection(rightCert); // Right cert, success signer.CheckSignature(coll, true); Assert.Null(signer.Certificate); cms.CheckSignature(coll, true); Assert.Null(cms.SignerInfos[0].Certificate); coll.Add(wrongCert); // Both right and wrong, success signer.CheckSignature(coll, true); Assert.Null(signer.Certificate); cms.CheckSignature(coll, true); Assert.Null(cms.SignerInfos[0].Certificate); coll = new X509Certificate2Collection(wrongCert); // Just wrong again, no accidental stateful match Assert.Throws <CryptographicException>(() => signer.CheckSignature(coll, true)); Assert.Throws <CryptographicException>(() => cms.CheckSignature(coll, true)); coll.Add(rightCert); // Wrong then right, success signer.CheckSignature(coll, true); Assert.Null(signer.Certificate); cms.CheckSignature(coll, true); Assert.Null(cms.SignerInfos[0].Certificate); } }
public static void CheckNoSignatureDocument() { SignedCms cms = new SignedCms(); cms.Decode(SignedDocuments.NoSignatureSignedWithAttributesAndCounterSignature); Assert.Equal(1, cms.Version); Assert.Equal(Oids.Pkcs7Data, cms.ContentInfo.ContentType.Value); Assert.Equal( "4D6963726F736F667420436F72706F726174696F6E", cms.ContentInfo.Content.ByteArrayToHex()); X509Certificate2Collection cmsCerts = cms.Certificates; Assert.Single(cmsCerts); SignerInfoCollection signers = cms.SignerInfos; Assert.Single(signers); SignerInfo signer = signers[0]; Assert.Equal(SubjectIdentifierType.NoSignature, signer.SignerIdentifier.Type); Assert.Null(signer.SignerIdentifier.Value); Assert.Null(signer.Certificate); Assert.Equal(Oids.Sha1, signer.DigestAlgorithm.Value); #if netcoreapp Assert.Equal("1.3.6.1.5.5.7.6.2", signer.SignatureAlgorithm.Value); Assert.Equal( "8B70D20D0477A35CD84AB962C10DC52FBA6FAD6B", signer.GetSignature().ByteArrayToHex()); #endif CryptographicAttributeObjectCollection signedAttrs = signer.SignedAttributes; Assert.Equal(3, signedAttrs.Count); Assert.Single(signedAttrs[0].Values); Assert.Single(signedAttrs[1].Values); Assert.Single(signedAttrs[2].Values); Pkcs9ContentType contentType = (Pkcs9ContentType)signedAttrs[0].Values[0]; Pkcs9SigningTime signingTime = (Pkcs9SigningTime)signedAttrs[1].Values[0]; Pkcs9MessageDigest messageDigest = (Pkcs9MessageDigest)signedAttrs[2].Values[0]; Assert.Equal(Oids.Pkcs7Data, contentType.ContentType.Value); Assert.Equal( new DateTimeOffset(2017, 11, 1, 17, 17, 17, TimeSpan.Zero), signingTime.SigningTime); Assert.Equal(DateTimeKind.Utc, signingTime.SigningTime.Kind); using (SHA1 sha1 = SHA1.Create()) { Assert.Equal( sha1.ComputeHash(cms.ContentInfo.Content).ByteArrayToHex(), messageDigest.MessageDigest.ByteArrayToHex()); } CryptographicAttributeObjectCollection unsignedAttrs = signer.UnsignedAttributes; Assert.Single(unsignedAttrs); // No need to check the contents, it's a CounterSigner (tested next) SignerInfoCollection counterSigners = signer.CounterSignerInfos; Assert.Single(counterSigners); SignerInfo counterSigner = counterSigners[0]; Assert.Equal(3, counterSigner.Version); Assert.Equal(SubjectIdentifierType.SubjectKeyIdentifier, counterSigner.SignerIdentifier.Type); Assert.Equal("6B4A6B92FDED07EE0119F3674A96D1A70D2A588D", (string)counterSigner.SignerIdentifier.Value); Assert.Equal(Oids.Sha1, counterSigner.DigestAlgorithm.Value); CryptographicAttributeObjectCollection csSignedAttrs = counterSigner.SignedAttributes; Assert.Equal(2, csSignedAttrs.Count); // RFC3369 says that the content-type attribute must not be present for counter-signers, but it is. // RFC2630 said that it "is not required". Pkcs9ContentType csContentType = (Pkcs9ContentType)csSignedAttrs[0].Values[0]; Pkcs9MessageDigest csMessageDigest = (Pkcs9MessageDigest)csSignedAttrs[1].Values[0]; Assert.Equal(Oids.Pkcs7Data, csContentType.ContentType.Value); Assert.Equal( "833378066BDCCBA7047EF6919843D181A57D6479", csMessageDigest.MessageDigest.ByteArrayToHex()); #if netcoreapp Assert.Equal(Oids.Rsa, counterSigner.SignatureAlgorithm.Value); Assert.Equal( "2155D226DD744166E582D040E60535210195050EA00F2C179897198521DABD0E" + "6B27750FD8BA5F9AAF58B4863B6226456F38553A22453CAF0A0F106766C7AB6F" + "3D6AFD106753DC50F8A6E4F9E5508426D236C2DBB4BCB8162FA42E995CBA16A3" + "40FD7C793569DF1B71368E68253299BC74E38312B40B8F52EAEDE10DF414A522", counterSigner.GetSignature().ByteArrayToHex()); #endif using (X509Certificate2 capiCert = Certificates.RSAKeyTransferCapi1.GetCertificate()) { Assert.Equal(capiCert, cmsCerts[0]); Assert.Equal(capiCert, counterSigner.Certificate); } // The counter-signer has a (real) signature, and a certificate, so CheckSignature // will pass counterSigner.CheckSignature(true); // The (primary) signer has a hash-only signature with no certificate, // so CheckSignature will fail. Assert.Throws <CryptographicException>(() => signer.CheckSignature(true)); // The (primary) signer is a NoSignature type, so CheckHash will succeed signer.CheckHash(); // The document has a NoSignature signer, so CheckHash will do something (and succeed). cms.CheckHash(); // Since the document's primary signer is NoSignature, CheckSignature will fail Assert.Throws <CryptographicException>(() => cms.CheckSignature(true)); }
public static void ReadRsaPkcs1CounterSigned() { SignedCms cms = new SignedCms(); cms.Decode(SignedDocuments.CounterSignedRsaPkcs1OneSigner); Assert.Equal(1, cms.Version); ContentInfo contentInfo = cms.ContentInfo; Assert.Equal("1.2.840.113549.1.7.1", contentInfo.ContentType.Value); Assert.Equal("4D6963726F736F667420436F72706F726174696F6E", contentInfo.Content.ByteArrayToHex()); SignerInfoCollection signers = cms.SignerInfos; Assert.Single(signers); SignerInfo signer = signers[0]; using (X509Certificate2 cert = Certificates.RSAKeyTransferCapi1.GetCertificate()) { X509Certificate2Collection certs = cms.Certificates; Assert.Single(certs); Assert.Equal(cert, certs[0]); Assert.Equal(cert, signer.Certificate); Assert.NotSame(certs[0], signer.Certificate); Assert.NotSame(cert, signer.Certificate); Assert.NotSame(cert, certs[0]); } Assert.Equal(SubjectIdentifierType.IssuerAndSerialNumber, signer.SignerIdentifier.Type); Assert.Equal(Oids.Sha1, signer.DigestAlgorithm.Value); #if netcoreapp Assert.Equal(Oids.Rsa, signer.SignatureAlgorithm.Value); Assert.Equal( "5A1717621D450130B3463662160EEC06F7AE77E017DD95F294E97A0BDD433FE6" + "B2CCB34FAAC33AEA50BFD7D9E78DC7174836284619F744278AE77B8495091E09" + "6EEF682D9CA95F6E81C7DDCEDDA6A12316B453C894B5000701EB09DF57A53B73" + "3A4E80DA27FA710870BD88C86E2FDB9DCA14D18BEB2F0C87E9632ABF02BE2FE3", signer.GetSignature().ByteArrayToHex()); #endif CryptographicAttributeObjectCollection signedAttrs = signer.SignedAttributes; Assert.Empty(signedAttrs); CryptographicAttributeObjectCollection unsignedAttrs = signer.UnsignedAttributes; Assert.Single(unsignedAttrs); Assert.Equal(Oids.CounterSigner, unsignedAttrs[0].Oid.Value); SignerInfoCollection counterSigners = signer.CounterSignerInfos; Assert.Single(counterSigners); SignerInfo counterSigner = counterSigners[0]; Assert.Equal(SubjectIdentifierType.SubjectKeyIdentifier, counterSigner.SignerIdentifier.Type); // Not universally true, but is in this case. Assert.Equal(signer.Certificate, counterSigner.Certificate); Assert.NotSame(signer.Certificate, counterSigner.Certificate); // Assert.NotThrows signer.CheckSignature(true); // Assert.NotThrows counterSigner.CheckSignature(true); // The document should be validly signed, then. // Assert.NotThrows cms.CheckSignature(true); // If CheckSignature succeeds then CheckHash cannot. Assert.Throws <CryptographicException>(() => counterSigner.CheckHash()); Assert.Throws <CryptographicException>(() => signer.CheckHash()); // Since there are no NoSignature signers, CheckHash won't throw. // Assert.NotThrows cms.CheckHash(); }
public static void ReadRsaPssDocument() { SignedCms cms = new SignedCms(); cms.Decode(SignedDocuments.RsaPssDocument); Assert.Equal(3, cms.Version); ContentInfo contentInfo = cms.ContentInfo; Assert.Equal("1.2.840.113549.1.7.1", contentInfo.ContentType.Value); Assert.Equal("54686973206973206120746573740D0A", contentInfo.Content.ByteArrayToHex()); X509Certificate2Collection certs = cms.Certificates; Assert.Single(certs); X509Certificate2 topLevelCert = certs[0]; Assert.Equal("localhost", topLevelCert.GetNameInfo(X509NameType.SimpleName, false)); Assert.Equal( new DateTimeOffset(2016, 3, 2, 2, 37, 54, TimeSpan.Zero), new DateTimeOffset(topLevelCert.NotBefore)); Assert.Equal( new DateTimeOffset(2017, 3, 2, 2, 37, 54, TimeSpan.Zero), new DateTimeOffset(topLevelCert.NotAfter)); SignerInfoCollection signers = cms.SignerInfos; Assert.Single(signers); SignerInfo signer = signers[0]; Assert.Equal(3, signer.Version); Assert.Equal(SubjectIdentifierType.SubjectKeyIdentifier, signer.SignerIdentifier.Type); Assert.Equal("1063CAB14FB14C47DC211C0E0285F3EE5946BF2D", signer.SignerIdentifier.Value); Assert.Equal("2.16.840.1.101.3.4.2.1", signer.DigestAlgorithm.Value); #if netcoreapp Assert.Equal("1.2.840.113549.1.1.10", signer.SignatureAlgorithm.Value); #endif CryptographicAttributeObjectCollection signedAttrs = signer.SignedAttributes; Assert.Equal(4, signedAttrs.Count); Assert.Equal("1.2.840.113549.1.9.3", signedAttrs[0].Oid.Value); Assert.Equal("1.2.840.113549.1.9.5", signedAttrs[1].Oid.Value); Assert.Equal("1.2.840.113549.1.9.4", signedAttrs[2].Oid.Value); Assert.Equal("1.2.840.113549.1.9.15", signedAttrs[3].Oid.Value); Assert.Equal(1, signedAttrs[0].Values.Count); Assert.Equal(1, signedAttrs[1].Values.Count); Assert.Equal(1, signedAttrs[2].Values.Count); Assert.Equal(1, signedAttrs[3].Values.Count); Pkcs9ContentType contentTypeAttr = (Pkcs9ContentType)signedAttrs[0].Values[0]; Assert.Equal("1.2.840.113549.1.7.1", contentTypeAttr.ContentType.Value); Pkcs9SigningTime signingTimeAttr = (Pkcs9SigningTime)signedAttrs[1].Values[0]; Assert.Equal( new DateTimeOffset(2017, 10, 26, 1, 6, 25, TimeSpan.Zero), new DateTimeOffset(signingTimeAttr.SigningTime)); Pkcs9MessageDigest messageDigestAttr = (Pkcs9MessageDigest)signedAttrs[2].Values[0]; Assert.Equal( "07849DC26FCBB2F3BD5F57BDF214BAE374575F1BD4E6816482324799417CB379", messageDigestAttr.MessageDigest.ByteArrayToHex()); Assert.IsType <Pkcs9AttributeObject>(signedAttrs[3].Values[0]); Assert.NotSame(signedAttrs[3].Oid, signedAttrs[3].Values[0].Oid); Assert.Equal( "306A300B060960864801650304012A300B0609608648016503040116300B0609" + "608648016503040102300A06082A864886F70D0307300E06082A864886F70D03" + "0202020080300D06082A864886F70D0302020140300706052B0E030207300D06" + "082A864886F70D0302020128", signedAttrs[3].Values[0].RawData.ByteArrayToHex()); #if netcoreapp Assert.Equal( "B93E81D141B3C9F159AB0021910635DC72E8E860BE43C28E5D53243D6DC247B7" + "D4F18C20195E80DEDCC75B29C43CE5047AD775B65BFC93589BD748B950C68BAD" + "DF1A4673130302BBDA8667D5DDE5EA91ECCB13A9B4C04F1C4842FEB1697B7669" + "C7692DD3BDAE13B5AA8EE3EB5679F3729D1DC4F2EB9DC89B7E8773F2F8C6108C" + "05", signer.GetSignature().ByteArrayToHex()); #endif CryptographicAttributeObjectCollection unsignedAttrs = signer.UnsignedAttributes; Assert.Empty(unsignedAttrs); SignerInfoCollection counterSigners = signer.CounterSignerInfos; Assert.Empty(counterSigners); X509Certificate2 signerCertificate = signer.Certificate; Assert.Equal( "CN=localhost, OU=.NET Framework, O=Microsoft Corp., L=Redmond, S=Washington, C=US", signerCertificate.SubjectName.Name); // CheckHash always throws for certificate-based signers. Assert.Throws <CryptographicException>(() => signer.CheckHash()); // At this time we cannot support the PSS parameters for this document. Assert.Throws <CryptographicException>(() => signer.CheckSignature(true)); // Since there are no NoSignature signers the document CheckHash will succeed. // Assert.NotThrows cms.CheckHash(); // Since at least one signer fails, the document signature will fail Assert.Throws <CryptographicException>(() => cms.CheckSignature(true)); }
public static void RemoveNegative() { CryptographicAttributeObjectCollection c = new CryptographicAttributeObjectCollection(); Assert.Throws <ArgumentNullException>(() => c.Remove(null)); }
public sealed unsafe override byte[] Encrypt(CmsRecipientCollection recipients, ContentInfo contentInfo, AlgorithmIdentifier contentEncryptionAlgorithm, X509Certificate2Collection originatorCerts, CryptographicAttributeObjectCollection unprotectedAttributes) { using (SafeCryptMsgHandle hCryptMsg = EncodeHelpers.CreateCryptMsgHandleToEncode(recipients, contentInfo.ContentType, contentEncryptionAlgorithm, originatorCerts, unprotectedAttributes)) { byte[] encodedContent; if (contentInfo.ContentType.Value.Equals(Oids.Pkcs7Data, StringComparison.OrdinalIgnoreCase)) { unsafe { byte[] content = contentInfo.Content; fixed(byte *pContent = content) { DATA_BLOB blob = new DATA_BLOB((IntPtr)pContent, (uint)(content.Length)); encodedContent = Interop.Crypt32.CryptEncodeObjectToByteArray(CryptDecodeObjectStructType.X509_OCTET_STRING, &blob); } } } else { encodedContent = contentInfo.Content; if (encodedContent.Length > 0) { // Windows will throw if it encounters indefinite length encoding. // Let's reencode if that is the case ReencodeIfUsingIndefiniteLengthEncodingOnOuterStructure(ref encodedContent); } } if (encodedContent.Length > 0) { // Pin to avoid copy during heap compaction fixed(byte *pinnedContent = encodedContent) { try { if (!Interop.Crypt32.CryptMsgUpdate(hCryptMsg, encodedContent, encodedContent.Length, fFinal: true)) { throw Marshal.GetLastWin32Error().ToCryptographicException(); } } finally { if (!object.ReferenceEquals(encodedContent, contentInfo.Content)) { Array.Clear(encodedContent, 0, encodedContent.Length); } } } } byte[] encodedMessage = hCryptMsg.GetMsgParamAsByteArray(CryptMsgParamType.CMSG_CONTENT_PARAM); return(encodedMessage); } }
// // This returns an allocated native memory block. Its lifetime (and that of any allocated subblocks it may point to) is that of "hb". // private static unsafe CMSG_ENVELOPED_ENCODE_INFO *CreateCmsEnvelopedEncodeInfo(CmsRecipientCollection recipients, AlgorithmIdentifier contentEncryptionAlgorithm, X509Certificate2Collection originatorCerts, CryptographicAttributeObjectCollection unprotectedAttributes, HeapBlockRetainer hb) { CMSG_ENVELOPED_ENCODE_INFO *pEnvelopedEncodeInfo = (CMSG_ENVELOPED_ENCODE_INFO *)(hb.Alloc(sizeof(CMSG_ENVELOPED_ENCODE_INFO))); pEnvelopedEncodeInfo->cbSize = sizeof(CMSG_ENVELOPED_ENCODE_INFO); pEnvelopedEncodeInfo->hCryptProv = IntPtr.Zero; string algorithmOidValue = contentEncryptionAlgorithm.Oid.Value; pEnvelopedEncodeInfo->ContentEncryptionAlgorithm.pszObjId = hb.AllocAsciiString(algorithmOidValue); // Desktop compat: Though it seems like we could copy over the contents of contentEncryptionAlgorithm.Parameters, that property is for retrieving information from decoded Cms's only, and it // massages the raw data so it wouldn't be usable here anyway. To hammer home that fact, the EncryptedCms constructor rather rudely forces contentEncryptionAlgorithm.Parameters to be the empty array. pEnvelopedEncodeInfo->ContentEncryptionAlgorithm.Parameters.cbData = 0; pEnvelopedEncodeInfo->ContentEncryptionAlgorithm.Parameters.pbData = IntPtr.Zero; pEnvelopedEncodeInfo->pvEncryptionAuxInfo = GenerateEncryptionAuxInfoIfNeeded(contentEncryptionAlgorithm, hb); int numRecipients = recipients.Count; pEnvelopedEncodeInfo->cRecipients = numRecipients; pEnvelopedEncodeInfo->rgpRecipients = IntPtr.Zero; CMSG_RECIPIENT_ENCODE_INFO *rgCmsRecipients = (CMSG_RECIPIENT_ENCODE_INFO *)(hb.Alloc(numRecipients, sizeof(CMSG_RECIPIENT_ENCODE_INFO))); for (int index = 0; index < numRecipients; index++) { rgCmsRecipients[index] = EncodeRecipientInfo(recipients[index], contentEncryptionAlgorithm, hb); } pEnvelopedEncodeInfo->rgCmsRecipients = rgCmsRecipients; int numCertificates = originatorCerts.Count; pEnvelopedEncodeInfo->cCertEncoded = numCertificates; pEnvelopedEncodeInfo->rgCertEncoded = null; if (numCertificates != 0) { DATA_BLOB *pCertEncoded = (DATA_BLOB *)(hb.Alloc(numCertificates, sizeof(DATA_BLOB))); for (int i = 0; i < numCertificates; i++) { byte[] certEncoded = originatorCerts[i].Export(X509ContentType.Cert); pCertEncoded[i].cbData = (uint)(certEncoded.Length); pCertEncoded[i].pbData = hb.AllocBytes(certEncoded); } pEnvelopedEncodeInfo->rgCertEncoded = pCertEncoded; } pEnvelopedEncodeInfo->cCrlEncoded = 0; pEnvelopedEncodeInfo->rgCrlEncoded = null; pEnvelopedEncodeInfo->cAttrCertEncoded = 0; pEnvelopedEncodeInfo->rgAttrCertEncoded = null; int numUnprotectedAttributes = unprotectedAttributes.Count; pEnvelopedEncodeInfo->cUnprotectedAttr = numUnprotectedAttributes; pEnvelopedEncodeInfo->rgUnprotectedAttr = null; if (numUnprotectedAttributes != 0) { CRYPT_ATTRIBUTE *pCryptAttribute = (CRYPT_ATTRIBUTE *)(hb.Alloc(numUnprotectedAttributes, sizeof(CRYPT_ATTRIBUTE))); for (int i = 0; i < numUnprotectedAttributes; i++) { CryptographicAttributeObject attribute = unprotectedAttributes[i]; pCryptAttribute[i].pszObjId = hb.AllocAsciiString(attribute.Oid.Value); AsnEncodedDataCollection values = attribute.Values; int numValues = values.Count; pCryptAttribute[i].cValue = numValues; DATA_BLOB *pValues = (DATA_BLOB *)(hb.Alloc(numValues, sizeof(DATA_BLOB))); for (int j = 0; j < numValues; j++) { byte[] rawData = values[j].RawData; pValues[j].cbData = (uint)(rawData.Length); pValues[j].pbData = hb.AllocBytes(rawData); } pCryptAttribute[i].rgValue = pValues; } pEnvelopedEncodeInfo->rgUnprotectedAttr = pCryptAttribute; } return(pEnvelopedEncodeInfo); }
public static SafeCryptMsgHandle CreateCryptMsgHandleToEncode(CmsRecipientCollection recipients, Oid innerContentType, AlgorithmIdentifier contentEncryptionAlgorithm, X509Certificate2Collection originatorCerts, CryptographicAttributeObjectCollection unprotectedAttributes) { using (HeapBlockRetainer hb = new HeapBlockRetainer()) { // Deep copy the CmsRecipients (and especially their underlying X509Certificate2 objects). This will prevent malicious callers from altering them or disposing them while we're performing // unsafe memory crawling inside them. recipients = recipients.DeepCopy(); // We must keep all the certificates inside recipients alive until the call to CryptMsgOpenToEncode() finishes. The CMSG_ENVELOPED_ENCODE_INFO* structure we passed to it // contains direct pointers to memory owned by the CERT_INFO memory block whose lifetime is that of the certificate. hb.KeepAlive(recipients); unsafe { CMSG_ENVELOPED_ENCODE_INFO *pEnvelopedEncodeInfo = CreateCmsEnvelopedEncodeInfo(recipients, contentEncryptionAlgorithm, originatorCerts, unprotectedAttributes, hb); SafeCryptMsgHandle hCryptMsg = Interop.Crypt32.CryptMsgOpenToEncode(MsgEncodingType.All, 0, CryptMsgType.CMSG_ENVELOPED, pEnvelopedEncodeInfo, innerContentType.Value, IntPtr.Zero); if (hCryptMsg == null || hCryptMsg.IsInvalid) { throw Marshal.GetLastWin32Error().ToCryptographicException(); } return(hCryptMsg); } } }
public sealed override unsafe byte[] Encrypt(CmsRecipientCollection recipients, ContentInfo contentInfo, AlgorithmIdentifier contentEncryptionAlgorithm, X509Certificate2Collection originatorCerts, CryptographicAttributeObjectCollection unprotectedAttributes) { using (SafeCryptMsgHandle hCryptMsg = EncodeHelpers.CreateCryptMsgHandleToEncode(recipients, contentInfo.ContentType, contentEncryptionAlgorithm, originatorCerts, unprotectedAttributes)) { byte[] encodedContent; if (contentInfo.ContentType.Value !.Equals(Oids.Pkcs7Data, StringComparison.OrdinalIgnoreCase)) { encodedContent = PkcsHelpers.EncodeOctetString(contentInfo.Content); }
public static void Test1() { var loader = (CertLoaderFromRawData)Certificates.RSAKeyTransferCapi1; ReadOnlyMemory <byte> pfxData = loader.PfxData; Pkcs12Info info = Pkcs12Info.Decode(pfxData, out int bytesConsumed); Assert.Equal(pfxData.Length, bytesConsumed); Assert.Equal(Pkcs12IntegrityMode.Password, info.IntegrityMode); CheckMac(info, loader.Password); ReadOnlyCollection <Pkcs12SafeContents> authSafe = info.AuthenticatedSafe; Assert.Same(authSafe, info.AuthenticatedSafe); Assert.Equal(2, authSafe.Count); Assert.Equal(Pkcs12ConfidentialityMode.None, authSafe[0].ConfidentialityMode); Assert.Equal(Pkcs12ConfidentialityMode.None, authSafe[1].ConfidentialityMode); List <Pkcs12SafeBag> safe0Bags = new List <Pkcs12SafeBag>(authSafe[0].GetBags()); Assert.Equal(1, safe0Bags.Count); Pkcs12ShroudedKeyBag shroudedKeyBag = Assert.IsType <Pkcs12ShroudedKeyBag>(safe0Bags[0]); CryptographicAttributeObjectCollection keyBagAttrs = shroudedKeyBag.Attributes; Assert.Same(keyBagAttrs, shroudedKeyBag.Attributes); Assert.Equal(2, keyBagAttrs.Count); Assert.Equal(Oids.LocalKeyId, keyBagAttrs[0].Oid.Value); Assert.Equal(1, keyBagAttrs[0].Values.Count); Pkcs9LocalKeyId keyKeyId = Assert.IsType <Pkcs9LocalKeyId>(keyBagAttrs[0].Values[0]); Assert.Equal("1.3.6.1.4.1.311.17.1", keyBagAttrs[1].Oid.Value); Assert.Equal(1, keyBagAttrs[1].Values.Count); Pkcs9AttributeObject cspNameAttr = Assert.IsType <Pkcs9AttributeObject>(keyBagAttrs[1].Values[0]); byte[] cspNameBytes = Encoding.BigEndianUnicode.GetBytes("Microsoft Strong Cryptographic Provider"); Assert.Equal( $"1E{cspNameBytes.Length:X2}{cspNameBytes.ByteArrayToHex()}", cspNameAttr.RawData.ByteArrayToHex()); List <Pkcs12SafeBag> safe1Bags = new List <Pkcs12SafeBag>(authSafe[1].GetBags()); Assert.Equal(1, safe0Bags.Count); Assert.IsType <Pkcs12CertBag>(safe1Bags[0]); Pkcs12CertBag certBag = (Pkcs12CertBag)safe1Bags[0]; Assert.True(certBag.IsX509Certificate, "certBag.IsX509Certificate"); Assert.InRange(certBag.EncodedCertificate.Length, loader.CerData.Length + 2, int.MaxValue); CryptographicAttributeObjectCollection certBagAttrs = certBag.Attributes; Assert.Same(certBagAttrs, certBag.Attributes); Assert.Equal(1, certBagAttrs.Count); Assert.Equal(Oids.LocalKeyId, certBagAttrs[0].Oid.Value); Assert.Equal(1, certBagAttrs[0].Values.Count); Pkcs9LocalKeyId certKeyId = Assert.IsType <Pkcs9LocalKeyId>(certBagAttrs[0].Values[0]); Assert.Equal(keyKeyId.KeyId.ByteArrayToHex(), certKeyId.KeyId.ByteArrayToHex()); byte[] data = { 9, 8, 7, 6, 5, 4, 3, 2, 1 }; byte[] encrypted; using (X509Certificate2 fromLoader = loader.GetCertificate()) using (X509Certificate2 fromBag = certBag.GetCertificate()) using (RSA loaderPub = fromLoader.GetRSAPublicKey()) { Assert.Equal(fromLoader.RawData, fromBag.RawData); encrypted = loaderPub.Encrypt(data, RSAEncryptionPadding.OaepSHA1); } int bytesRead; using (RSA rsa = RSA.Create()) { rsa.ImportEncryptedPkcs8PrivateKey( loader.Password, shroudedKeyBag.EncryptedPkcs8PrivateKey.Span, out bytesRead); byte[] dec = rsa.Decrypt(encrypted, RSAEncryptionPadding.OaepSHA1); Assert.Equal(data, dec); } Assert.Equal(shroudedKeyBag.EncryptedPkcs8PrivateKey.Length, bytesRead); }
private byte[] Encrypt( CmsRecipientCollection recipients, ContentInfo contentInfo, AlgorithmIdentifier contentEncryptionAlgorithm, X509Certificate2Collection originatorCerts, CryptographicAttributeObjectCollection unprotectedAttributes, byte[] encryptedContent, byte[] cek, byte[] parameterBytes) { EnvelopedDataAsn envelopedData = new EnvelopedDataAsn { EncryptedContentInfo = { ContentType = contentInfo.ContentType.Value, ContentEncryptionAlgorithm = { Algorithm = contentEncryptionAlgorithm.Oid, Parameters = parameterBytes, }, EncryptedContent = encryptedContent, }, }; if (unprotectedAttributes != null && unprotectedAttributes.Count > 0) { List <AttributeAsn> attrList = CmsSigner.BuildAttributes(unprotectedAttributes); envelopedData.UnprotectedAttributes = PkcsHelpers.NormalizeAttributeSet(attrList.ToArray()); } if (originatorCerts != null && originatorCerts.Count > 0) { CertificateChoiceAsn[] certs = new CertificateChoiceAsn[originatorCerts.Count]; for (int i = 0; i < originatorCerts.Count; i++) { certs[i].Certificate = originatorCerts[i].RawData; } envelopedData.OriginatorInfo = new OriginatorInfoAsn { CertificateSet = certs, }; } envelopedData.RecipientInfos = new RecipientInfoAsn[recipients.Count]; bool allRecipientsVersion0 = true; for (var i = 0; i < recipients.Count; i++) { CmsRecipient recipient = recipients[i]; bool v0Recipient; switch (recipient.Certificate.GetKeyAlgorithm()) { case Oids.Rsa: envelopedData.RecipientInfos[i].Ktri = MakeKtri(cek, recipient, out v0Recipient); break; default: throw new CryptographicException( SR.Cryptography_Cms_UnknownAlgorithm, recipient.Certificate.GetKeyAlgorithm()); } allRecipientsVersion0 = allRecipientsVersion0 && v0Recipient; } // https://tools.ietf.org/html/rfc5652#section-6.1 // // v4 (RFC 3852): // * OriginatorInfo contains certificates with type other (not supported) // * OriginatorInfo contains crls with type other (not supported) // v3 (RFC 3369): // * OriginatorInfo contains v2 attribute certificates (not supported) // * Any PWRI (password) recipients are present (not supported) // * Any ORI (other) recipients are present (not supported) // v2 (RFC 2630): // * OriginatorInfo is present // * Any RecipientInfo has a non-zero version number // * UnprotectedAttrs is present // v1 (not defined for EnvelopedData) // v0 (RFC 2315): // * Anything not already matched if (envelopedData.OriginatorInfo != null || !allRecipientsVersion0 || envelopedData.UnprotectedAttributes != null) { envelopedData.Version = 2; } using (AsnWriter writer = new AsnWriter(AsnEncodingRules.DER)) { envelopedData.Encode(writer); return(PkcsHelpers.EncodeContentInfo(writer.Encode(), Oids.Pkcs7Enveloped)); } }
public static void Nullary() { CryptographicAttributeObjectCollection c = new CryptographicAttributeObjectCollection(); AssertEquals(c, Array.Empty <CryptographicAttributeObject>()); }
public static void ReadRsaPkcs1DoubleCounterSigned() { SignedCms cms = new SignedCms(); cms.Decode(SignedDocuments.OneRsaSignerTwoRsaCounterSigners); Assert.Equal(1, cms.Version); ContentInfo contentInfo = cms.ContentInfo; Assert.Equal("1.2.840.113549.1.7.1", contentInfo.ContentType.Value); Assert.Equal("4D6963726F736F667420436F72706F726174696F6E", contentInfo.Content.ByteArrayToHex()); SignerInfoCollection signers = cms.SignerInfos; Assert.Single(signers); SignerInfo signer = signers[0]; using (X509Certificate2 cert = Certificates.RSAKeyTransferCapi1.GetCertificate()) { X509Certificate2Collection certs = cms.Certificates; Assert.Equal(2, certs.Count); Assert.Equal(cert, certs[1]); Assert.Equal(cert, signer.Certificate); Assert.NotSame(certs[1], signer.Certificate); Assert.NotSame(cert, signer.Certificate); Assert.NotSame(cert, certs[1]); } Assert.Equal(SubjectIdentifierType.IssuerAndSerialNumber, signer.SignerIdentifier.Type); Assert.Equal(Oids.Sha1, signer.DigestAlgorithm.Value); #if netcoreapp Assert.Equal(Oids.Rsa, signer.SignatureAlgorithm.Value); Assert.Equal( "5A1717621D450130B3463662160EEC06F7AE77E017DD95F294E97A0BDD433FE6" + "B2CCB34FAAC33AEA50BFD7D9E78DC7174836284619F744278AE77B8495091E09" + "6EEF682D9CA95F6E81C7DDCEDDA6A12316B453C894B5000701EB09DF57A53B73" + "3A4E80DA27FA710870BD88C86E2FDB9DCA14D18BEB2F0C87E9632ABF02BE2FE3", signer.GetSignature().ByteArrayToHex()); #endif CryptographicAttributeObjectCollection signedAttrs = signer.SignedAttributes; Assert.Empty(signedAttrs); CryptographicAttributeObjectCollection unsignedAttrs = signer.UnsignedAttributes; Assert.Equal(2, unsignedAttrs.Count); Assert.Equal(Oids.CounterSigner, unsignedAttrs[0].Oid.Value); SignerInfoCollection counterSigners = signer.CounterSignerInfos; Assert.Equal(2, counterSigners.Count); SignerInfo cs1 = counterSigners[0]; SignerInfo cs2 = counterSigners[1]; Assert.Equal(SubjectIdentifierType.SubjectKeyIdentifier, cs1.SignerIdentifier.Type); // Not universally true, but is in this case. Assert.Equal(signer.Certificate, cs1.Certificate); Assert.NotSame(signer.Certificate, cs1.Certificate); Assert.Equal(SubjectIdentifierType.IssuerAndSerialNumber, cs2.SignerIdentifier.Type); Assert.NotEqual(signer.Certificate, cs2.Certificate); // Assert.NotThrows signer.CheckSignature(true); // Assert.NotThrows cs1.CheckSignature(true); // Assert.NotThrows cs2.CheckSignature(true); // The document should be validly signed, then. // Assert.NotThrows cms.CheckSignature(true); #if netcoreapp Assert.Equal( "1AA282DBED4D862D7CEA30F803E790BDB0C97EE852778CEEDDCD94BB9304A155" + "2E60A8D36052AC8C2D28755F3B2F473824100AB3A6ABD4C15ABD77E0FFE13D0D" + "F253BCD99C718FA673B6CB0CBBC68CE5A4AC671298C0A07C7223522E0E7FFF15" + "CEDBAB55AAA99588517674671691065EB083FB729D1E9C04B2BF99A9953DAA5E", cs2.GetSignature().ByteArrayToHex()); #endif // If CheckSignature succeeds then CheckHash cannot. Assert.Throws <CryptographicException>(() => cs1.CheckHash()); Assert.Throws <CryptographicException>(() => cs2.CheckHash()); Assert.Throws <CryptographicException>(() => signer.CheckHash()); // Since there are no NoSignature signers, CheckHash won't throw. // Assert.NotThrows cms.CheckHash(); }
public sealed override DecryptorPal Decode(ReadOnlySpan <byte> encodedMessage, out int version, out ContentInfo contentInfo, out AlgorithmIdentifier contentEncryptionAlgorithm, out X509Certificate2Collection originatorCerts, out CryptographicAttributeObjectCollection unprotectedAttributes) { return(DecryptorPalWindows.Decode(encodedMessage, out version, out contentInfo, out contentEncryptionAlgorithm, out originatorCerts, out unprotectedAttributes)); }
public static void ReadIndefiniteEncodingNoMac(int trailingByteCount) { ReadOnlyMemory <byte> source = PadContents(Pkcs12Documents.IndefiniteEncodingNoMac, trailingByteCount); Pkcs12Info info = Pkcs12Info.Decode( source, out int bytesRead, skipCopy: true); Assert.Equal(Pkcs12Documents.IndefiniteEncodingNoMac.Length, bytesRead); Assert.Equal(Pkcs12IntegrityMode.None, info.IntegrityMode); ReadOnlyCollection <Pkcs12SafeContents> safes = info.AuthenticatedSafe; Assert.Equal(2, safes.Count); Pkcs12SafeContents firstSafe = safes[0]; Pkcs12SafeContents secondSafe = safes[1]; Assert.Equal(Pkcs12ConfidentialityMode.None, firstSafe.ConfidentialityMode); Assert.Equal(Pkcs12ConfidentialityMode.None, secondSafe.ConfidentialityMode); Assert.True(firstSafe.IsReadOnly, "firstSafe.IsReadOnly"); Assert.True(secondSafe.IsReadOnly, "secondSafe.IsReadOnly"); Pkcs12SafeBag[] firstContents = firstSafe.GetBags().ToArray(); Pkcs12SafeBag[] secondContents = secondSafe.GetBags().ToArray(); Assert.Equal(1, firstContents.Length); Assert.Equal(1, secondContents.Length); Pkcs12KeyBag keyBag = Assert.IsType <Pkcs12KeyBag>(firstContents[0]); Pkcs12CertBag certBag = Assert.IsType <Pkcs12CertBag>(secondContents[0]); CryptographicAttributeObjectCollection keyBagAttrs = keyBag.Attributes; CryptographicAttributeObjectCollection certBagAttrs = certBag.Attributes; Assert.Equal(2, keyBagAttrs.Count); Assert.Equal(2, certBagAttrs.Count); Assert.Equal(Oids.FriendlyName, keyBagAttrs[0].Oid.Value); Assert.Equal(1, keyBagAttrs[0].Values.Count); Assert.Equal(Oids.LocalKeyId, keyBagAttrs[1].Oid.Value); Assert.Equal(1, keyBagAttrs[1].Values.Count); Pkcs9AttributeObject keyFriendlyName = Assert.IsAssignableFrom <Pkcs9AttributeObject>(keyBagAttrs[0].Values[0]); Pkcs9LocalKeyId keyKeyId = Assert.IsType <Pkcs9LocalKeyId>(keyBagAttrs[1].Values[0]); Assert.Equal(Oids.FriendlyName, certBagAttrs[0].Oid.Value); Assert.Equal(1, certBagAttrs[0].Values.Count); Assert.Equal(Oids.LocalKeyId, certBagAttrs[1].Oid.Value); Assert.Equal(1, certBagAttrs[1].Values.Count); Pkcs9AttributeObject certFriendlyName = Assert.IsAssignableFrom <Pkcs9AttributeObject>(certBagAttrs[0].Values[0]); Pkcs9LocalKeyId certKeyId = Assert.IsType <Pkcs9LocalKeyId>(certBagAttrs[1].Values[0]); // This PFX gave a friendlyName value of "cert" to both the key and the cert. Assert.Equal("1E080063006500720074", keyFriendlyName.RawData.ByteArrayToHex()); Assert.Equal(keyFriendlyName.RawData, certFriendlyName.RawData); // The private key (KeyBag) and the public key (CertBag) are matched from their keyId value. Assert.Equal("0414EDF3D122CF623CF0CFC9CD226261E8415A83E630", keyKeyId.RawData.ByteArrayToHex()); Assert.Equal("EDF3D122CF623CF0CFC9CD226261E8415A83E630", keyKeyId.KeyId.ByteArrayToHex()); Assert.Equal(keyKeyId.RawData, certKeyId.RawData); using (X509Certificate2 cert = certBag.GetCertificate()) using (RSA privateKey = RSA.Create()) using (RSA publicKey = cert.GetRSAPublicKey()) { privateKey.ImportPkcs8PrivateKey(keyBag.Pkcs8PrivateKey.Span, out _); Assert.Equal( publicKey.ExportSubjectPublicKeyInfo().ByteArrayToHex(), privateKey.ExportSubjectPublicKeyInfo().ByteArrayToHex()); } }
// constructors public EnvelopedCms () { _certs = new X509Certificate2Collection (); _recipients = new RecipientInfoCollection (); _uattribs = new CryptographicAttributeObjectCollection (); }
/// <summary> /// Encrypt and encode a CMS. Return value is the RFC-compliant representation of the CMS that can be transmitted "on the wire." /// </summary> public abstract byte[] Encrypt(CmsRecipientCollection recipients, ContentInfo contentInfo, AlgorithmIdentifier contentEncryptionAlgorithm, X509Certificate2Collection originatorCerts, CryptographicAttributeObjectCollection unprotectedAttributes);
/// <summary> /// Decode an encoded CMS. /// Call RecipientInfos on the returned pal object to get the recipients. /// Call TryDecrypt() on the returned pal object to attempt a decrypt for a single recipient. /// </summary> public abstract DecryptorPal Decode(byte[] encodedMessage, out int version, out ContentInfo contentInfo, out AlgorithmIdentifier contentEncryptionAlgorithm, out X509Certificate2Collection originatorCerts, out CryptographicAttributeObjectCollection unprotectedAttributes);
internal static DecryptorPalWindows Decode( ReadOnlySpan <byte> encodedMessage, out int version, out ContentInfo contentInfo, out AlgorithmIdentifier contentEncryptionAlgorithm, out X509Certificate2Collection originatorCerts, out CryptographicAttributeObjectCollection unprotectedAttributes ) { SafeCryptMsgHandle?hCryptMsg = null; try { hCryptMsg = Interop.Crypt32.CryptMsgOpenToDecode(MsgEncodingType.All, 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); if (hCryptMsg == null || hCryptMsg.IsInvalid) { throw Marshal.GetLastPInvokeError().ToCryptographicException(); } if (!Interop.Crypt32.CryptMsgUpdate( hCryptMsg, ref MemoryMarshal.GetReference(encodedMessage), encodedMessage.Length, fFinal: true)) { throw Marshal.GetLastPInvokeError().ToCryptographicException(); } CryptMsgType cryptMsgType = hCryptMsg.GetMessageType(); if (cryptMsgType != CryptMsgType.CMSG_ENVELOPED) { throw ErrorCode.CRYPT_E_INVALID_MSG_TYPE.ToCryptographicException(); } version = hCryptMsg.GetVersion(); contentInfo = hCryptMsg.GetContentInfo(); AlgorithmIdentifierAsn contentEncryptionAlgorithmAsn; using (SafeHandle sh = hCryptMsg.GetMsgParamAsMemory(CryptMsgParamType.CMSG_ENVELOPE_ALGORITHM_PARAM)) { unsafe { CRYPT_ALGORITHM_IDENTIFIER *pCryptAlgorithmIdentifier = (CRYPT_ALGORITHM_IDENTIFIER *)(sh.DangerousGetHandle()); contentEncryptionAlgorithm = (*pCryptAlgorithmIdentifier).ToAlgorithmIdentifier(); contentEncryptionAlgorithmAsn.Algorithm = contentEncryptionAlgorithm.Oid.Value !; contentEncryptionAlgorithmAsn.Parameters = (*pCryptAlgorithmIdentifier).Parameters.ToByteArray(); } } originatorCerts = hCryptMsg.GetOriginatorCerts(); unprotectedAttributes = hCryptMsg.GetUnprotectedAttributes(); RecipientInfoCollection recipientInfos = CreateRecipientInfos(hCryptMsg); return(new DecryptorPalWindows(hCryptMsg, recipientInfos, contentEncryptionAlgorithmAsn)); } catch { hCryptMsg?.Dispose(); throw; } }