private bool VerifyCounterSignature (PKCS7.SignerInfo cs, byte[] signature) { // SEQUENCE { // INTEGER 1 if (cs.Version != 1) return false; // SEQUENCE { // SEQUENCE { string contentType = null; ASN1 messageDigest = null; for (int i=0; i < cs.AuthenticatedAttributes.Count; i++) { // SEQUENCE { // OBJECT IDENTIFIER ASN1 attr = (ASN1) cs.AuthenticatedAttributes [i]; string oid = ASN1Convert.ToOid (attr[0]); switch (oid) { case "1.2.840.113549.1.9.3": // contentType contentType = ASN1Convert.ToOid (attr[1][0]); break; case "1.2.840.113549.1.9.4": // messageDigest messageDigest = attr[1][0]; break; case "1.2.840.113549.1.9.5": // SEQUENCE { // OBJECT IDENTIFIER // signingTime (1 2 840 113549 1 9 5) // SET { // UTCTime '030124013651Z' // } // } timestamp = ASN1Convert.ToDateTime (attr[1][0]); break; default: break; } } if (contentType != PKCS7.Oid.data) return false; // verify message digest if (messageDigest == null) return false; // TODO: must be read from the ASN.1 structure string hashName = null; switch (messageDigest.Length) { case 16: hashName = "MD5"; break; case 20: hashName = "SHA1"; break; } HashAlgorithm ha = HashAlgorithm.Create (hashName); if (!messageDigest.CompareValue (ha.ComputeHash (signature))) return false; // verify signature byte[] counterSignature = cs.Signature; // change to SET OF (not [0]) as per PKCS #7 1.5 ASN1 aa = new ASN1 (0x31); foreach (ASN1 a in cs.AuthenticatedAttributes) aa.Add (a); byte[] p7hash = ha.ComputeHash (aa.GetBytes ()); // we need to try all certificates string issuer = cs.IssuerName; byte[] serial = cs.SerialNumber; foreach (X509Certificate x509 in coll) { if (CompareIssuerSerial (issuer, serial, x509)) { if (x509.PublicKey.Length > counterSignature.Length) { RSACryptoServiceProvider rsa = (RSACryptoServiceProvider) x509.RSA; // we need to HACK around bad (PKCS#1 1.5) signatures made by Verisign Timestamp Service // and this means copying stuff into our own RSAManaged to get the required flexibility RSAManaged rsam = new RSAManaged (); rsam.ImportParameters (rsa.ExportParameters (false)); if (PKCS1.Verify_v15 (rsam, ha, p7hash, counterSignature, true)) { timestampChain.LoadCertificates (coll); return (timestampChain.Build (x509)); } } } } // no certificate can verify this signature! return false; }
//private bool VerifySignature (ASN1 cs, byte[] calculatedMessageDigest, string hashName) private bool VerifySignature (PKCS7.SignedData sd, byte[] calculatedMessageDigest, HashAlgorithm ha) { string contentType = null; ASN1 messageDigest = null; // string spcStatementType = null; // string spcSpOpusInfo = null; for (int i=0; i < sd.SignerInfo.AuthenticatedAttributes.Count; i++) { ASN1 attr = (ASN1) sd.SignerInfo.AuthenticatedAttributes [i]; string oid = ASN1Convert.ToOid (attr[0]); switch (oid) { case "1.2.840.113549.1.9.3": // contentType contentType = ASN1Convert.ToOid (attr[1][0]); break; case "1.2.840.113549.1.9.4": // messageDigest messageDigest = attr[1][0]; break; case "1.3.6.1.4.1.311.2.1.11": // spcStatementType (Microsoft code signing) // possible values // - individualCodeSigning (1 3 6 1 4 1 311 2 1 21) // - commercialCodeSigning (1 3 6 1 4 1 311 2 1 22) // spcStatementType = ASN1Convert.ToOid (attr[1][0][0]); break; case "1.3.6.1.4.1.311.2.1.12": // spcSpOpusInfo (Microsoft code signing) /* try { spcSpOpusInfo = System.Text.Encoding.UTF8.GetString (attr[1][0][0][0].Value); } catch (NullReferenceException) { spcSpOpusInfo = null; }*/ break; default: break; } } if (contentType != spcIndirectDataContext) return false; // verify message digest if (messageDigest == null) return false; if (!messageDigest.CompareValue (calculatedMessageDigest)) return false; // verify signature string hashOID = CryptoConfig.MapNameToOID (ha.ToString ()); // change to SET OF (not [0]) as per PKCS #7 1.5 ASN1 aa = new ASN1 (0x31); foreach (ASN1 a in sd.SignerInfo.AuthenticatedAttributes) aa.Add (a); ha.Initialize (); byte[] p7hash = ha.ComputeHash (aa.GetBytes ()); byte[] signature = sd.SignerInfo.Signature; // we need to find the specified certificate string issuer = sd.SignerInfo.IssuerName; byte[] serial = sd.SignerInfo.SerialNumber; foreach (X509Certificate x509 in coll) { if (CompareIssuerSerial (issuer, serial, x509)) { // don't verify is key size don't match if (x509.PublicKey.Length > (signature.Length >> 3)) { // return the signing certificate even if the signature isn't correct // (required behaviour for 2.0 support) signingCertificate = x509; RSACryptoServiceProvider rsa = (RSACryptoServiceProvider) x509.RSA; if (rsa.VerifyHash (p7hash, hashOID, signature)) { signerChain.LoadCertificates (coll); trustedRoot = signerChain.Build (x509); break; } } } } // timestamp signature is optional if (sd.SignerInfo.UnauthenticatedAttributes.Count == 0) { trustedTimestampRoot = true; } else { for (int i = 0; i < sd.SignerInfo.UnauthenticatedAttributes.Count; i++) { ASN1 attr = (ASN1) sd.SignerInfo.UnauthenticatedAttributes[i]; string oid = ASN1Convert.ToOid (attr[0]); switch (oid) { case PKCS7.Oid.countersignature: // SEQUENCE { // OBJECT IDENTIFIER // countersignature (1 2 840 113549 1 9 6) // SET { PKCS7.SignerInfo cs = new PKCS7.SignerInfo (attr[1]); trustedTimestampRoot = VerifyCounterSignature (cs, signature); break; default: // we don't support other unauthenticated attributes break; } } } return (trustedRoot && trustedTimestampRoot); }
private bool VerifySignature(PKCS7.SignedData sd, byte[] calculatedMessageDigest, HashAlgorithm ha) { string a = null; ASN1 aSN = null; for (int i = 0; i < sd.SignerInfo.AuthenticatedAttributes.Count; i++) { ASN1 aSN2 = (ASN1)sd.SignerInfo.AuthenticatedAttributes[i]; switch (ASN1Convert.ToOid(aSN2[0])) { case "1.2.840.113549.1.9.3": a = ASN1Convert.ToOid(aSN2[1][0]); break; case "1.2.840.113549.1.9.4": aSN = aSN2[1][0]; break; } } if (a != "1.3.6.1.4.1.311.2.1.4") { return(false); } if (aSN == null) { return(false); } if (!aSN.CompareValue(calculatedMessageDigest)) { return(false); } string str = CryptoConfig.MapNameToOID(ha.ToString()); ASN1 aSN3 = new ASN1(49); foreach (ASN1 authenticatedAttribute in sd.SignerInfo.AuthenticatedAttributes) { aSN3.Add(authenticatedAttribute); } ha.Initialize(); byte[] rgbHash = ha.ComputeHash(aSN3.GetBytes()); byte[] signature = sd.SignerInfo.Signature; string issuerName = sd.SignerInfo.IssuerName; byte[] serialNumber = sd.SignerInfo.SerialNumber; foreach (X509Certificate item in coll) { if (CompareIssuerSerial(issuerName, serialNumber, item) && item.PublicKey.Length > signature.Length >> 3) { signingCertificate = item; RSACryptoServiceProvider rSACryptoServiceProvider = (RSACryptoServiceProvider)item.RSA; if (rSACryptoServiceProvider.VerifyHash(rgbHash, str, signature)) { signerChain.LoadCertificates(coll); trustedRoot = signerChain.Build(item); break; } } } if (sd.SignerInfo.UnauthenticatedAttributes.Count == 0) { trustedTimestampRoot = true; } else { for (int j = 0; j < sd.SignerInfo.UnauthenticatedAttributes.Count; j++) { ASN1 aSN4 = (ASN1)sd.SignerInfo.UnauthenticatedAttributes[j]; switch (ASN1Convert.ToOid(aSN4[0])) { case "1.2.840.113549.1.9.6": { PKCS7.SignerInfo cs = new PKCS7.SignerInfo(aSN4[1]); trustedTimestampRoot = VerifyCounterSignature(cs, signature); break; } } } } return(trustedRoot && trustedTimestampRoot); }
private bool VerifyCounterSignature(PKCS7.SignerInfo cs, byte[] signature) { if (cs.Version != 1) { return(false); } string a = null; ASN1 aSN = null; for (int i = 0; i < cs.AuthenticatedAttributes.Count; i++) { ASN1 aSN2 = (ASN1)cs.AuthenticatedAttributes[i]; switch (ASN1Convert.ToOid(aSN2[0])) { case "1.2.840.113549.1.9.3": a = ASN1Convert.ToOid(aSN2[1][0]); break; case "1.2.840.113549.1.9.4": aSN = aSN2[1][0]; break; case "1.2.840.113549.1.9.5": timestamp = ASN1Convert.ToDateTime(aSN2[1][0]); break; } } if (a != "1.2.840.113549.1.7.1") { return(false); } if (aSN == null) { return(false); } string hashName = null; switch (aSN.Length) { case 16: hashName = "MD5"; break; case 20: hashName = "SHA1"; break; } HashAlgorithm hashAlgorithm = HashAlgorithm.Create(hashName); if (!aSN.CompareValue(hashAlgorithm.ComputeHash(signature))) { return(false); } byte[] signature2 = cs.Signature; ASN1 aSN3 = new ASN1(49); foreach (ASN1 authenticatedAttribute in cs.AuthenticatedAttributes) { aSN3.Add(authenticatedAttribute); } byte[] hashValue = hashAlgorithm.ComputeHash(aSN3.GetBytes()); string issuerName = cs.IssuerName; byte[] serialNumber = cs.SerialNumber; foreach (X509Certificate item in coll) { if (CompareIssuerSerial(issuerName, serialNumber, item) && item.PublicKey.Length > signature2.Length) { RSACryptoServiceProvider rSACryptoServiceProvider = (RSACryptoServiceProvider)item.RSA; RSAManaged rSAManaged = new RSAManaged(); rSAManaged.ImportParameters(rSACryptoServiceProvider.ExportParameters(includePrivateParameters: false)); if (PKCS1.Verify_v15(rSAManaged, hashAlgorithm, hashValue, signature2, tryNonStandardEncoding: true)) { timestampChain.LoadCertificates(coll); return(timestampChain.Build(item)); } } } return(false); }
private bool VerifyCounterSignature(PKCS7.SignerInfo cs, byte[] signature) { // SEQUENCE { // INTEGER 1 if (cs.Version != 1) { return(false); } // SEQUENCE { // SEQUENCE { string contentType = null; ASN1 messageDigest = null; for (int i = 0; i < cs.AuthenticatedAttributes.Count; i++) { // SEQUENCE { // OBJECT IDENTIFIER ASN1 attr = (ASN1)cs.AuthenticatedAttributes [i]; string oid = ASN1Convert.ToOid(attr[0]); switch (oid) { case "1.2.840.113549.1.9.3": // contentType contentType = ASN1Convert.ToOid(attr[1][0]); break; case "1.2.840.113549.1.9.4": // messageDigest messageDigest = attr[1][0]; break; case "1.2.840.113549.1.9.5": // SEQUENCE { // OBJECT IDENTIFIER // signingTime (1 2 840 113549 1 9 5) // SET { // UTCTime '030124013651Z' // } // } timestamp = ASN1Convert.ToDateTime(attr[1][0]); break; default: break; } } if (contentType != PKCS7.Oid.data) { return(false); } // verify message digest if (messageDigest == null) { return(false); } // TODO: must be read from the ASN.1 structure string hashName = null; switch (messageDigest.Length) { case 16: hashName = "MD5"; break; case 20: hashName = "SHA1"; break; } HashAlgorithm ha = HashAlgorithm.Create(hashName); if (!messageDigest.CompareValue(ha.ComputeHash(signature))) { return(false); } // verify signature byte[] counterSignature = cs.Signature; string hashOID = CryptoConfig.MapNameToOID(hashName); // change to SET OF (not [0]) as per PKCS #7 1.5 ASN1 aa = new ASN1(0x31); foreach (ASN1 a in cs.AuthenticatedAttributes) { aa.Add(a); } byte[] p7hash = ha.ComputeHash(aa.GetBytes()); // we need to try all certificates string issuer = cs.IssuerName; byte[] serial = cs.SerialNumber; foreach (X509Certificate x509 in coll) { if (CompareIssuerSerial(issuer, serial, x509)) { // don't verify if key size don't match if (x509.PublicKey.Length > (counterSignature.Length >> 3)) { RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)x509.RSA; if (rsa.VerifyHash(p7hash, hashOID, counterSignature)) { timestampChain.LoadCertificates(coll); return(timestampChain.Build(x509)); } } } } // no certificate can verify this signature! return(false); }