private IASSod(byte[] sod) { //Create asn1 structure of IAS sod object var asn1 = ASN1Tag.Parse(sod, true); //Take root element that represents all data signed var root = asn1.Child(0); root.Child(0, 06).Verify(OID.ToByteArray(OID.OIDsignedData)); //06 Verify that result is a OBJECT IDENTIFIER //Struttura che negli altri elementi verrà firmata SignedDataObject = root.DeepChild(1, 0, 2); SignedDataObject.Child(0, 06).Verify(OID.ToByteArray(OID.OIDldsSecurityObject)); //06 Verify that result is a OBJECT IDENTIFIER /*GET SIGNED DATA THAT CONTAINS HASHED INFORMATION OF: * - ID servizi * - Seriale carta * - Certificato utente * - Chiave pubblica di internal authentication * - Chiave pubblica di internal authentication per i servizi*/ SignedData = SignedDataObject.DeepChild(1, 0).Child(0, 0x30); //0x30 Verify that result is a SEQUENCE //GET DOCUMENT SIGNER CERTIFICATE //This object can be parsed to X509Certificate2 class costrusctor DSCertificate = root.DeepChild(1, 0, 3).Child(0, 0x30); //0x30 Verify that result is a SEQUENCE //GET SIGNER INFO var signerInfo = root.DeepChild(1, 0, 4).Child(0, 0x30); //0x30 Verify that result is a SEQUENCE /*GET INFORMATION OF ISSUER FROM SIGNER INFO * La struttura dati contenuta si avvicina alla seguente: * 0 SET (1 elem) * 0.0 SEQUENCE (2 elem) * 0.0.0 OBJECT IDENTIFIER (2.5.4.3 commonName (X.520 DN component)) * 0.0.1 PrintableString (Italian Country Signer CA - TEST) * 1 SET (1 elem) * 1.0 SEQUENCE (2 elem) * 1.0.0 OBJECT IDENTIFIER (2.5.4.11 organizationalUnitName (X.520 DN component)) * 1.0.1 PrintableString (National Electronic Center of State Police) * 2 SET (1 elem) * 2.0 SEQUENCE (2 elem) * 2.0.0 OBJECT IDENTIFIER (2.5.4.10 organizationName (X.520 DN component)) * 2.0.1 PrintableString (Ministry of Interior) * 3 SET (1 elem) * 3.0 SEQUENCE (2 elem) * 3.0.0 OBJECT IDENTIFIER (2.5.4.6 countryName (X.520 DN component)) * 3.0.1 PrintableString (IT)*/ IssuerName = signerInfo.DeepChild(1).Child(0, 0x30); //0x30 Verify that result is a SEQUENCE /*GET INFORMATION OF SIGNER CERTIFICATE SERIAL NUMBER FROM DS CERT * La struttura dati contenuta si avvicina alla seguente: * 0 INTEGER (value of serial number)*/ SerialNumber = signerInfo.DeepChild(1).Child(1, 0x02); //02 Verify that result is a INTEGER /*GET INFORMATION ABOUT SIGNER FROM DS CERT * La struttura dati contenuta si avvicina alla seguente: * 0 SEQUENCE (2 elem) * 0.0 OBJECT IDENTIFIER (1.2.840.113549.1.9.3 OIDcontentType) * 0.1 SET (1 elem) * 0.1.0 OBJECT IDENTIFIER (2.23.136.1.1.1 Security) * 1 SEQUENCE (2 elem) * 1.0 OBJECT IDENTIFIER (1.2.840.113549.1.9.4 OIDmessageDigest) * 1.1 SET (1 elem) * 1.1.0 OCTET STRING (F92C82AE7A944DCFFE4CCD0B6CAFA9D0134ED16EBEEFE6D9A44B641920F99BA9... (hash)) */ SignatureAlgoritmIdentifier = signerInfo.Child(3, 0xA0); //0xA0 Verify that result is a CONTEXT_SPECIFIC //Verify data structure of SignerInfo object SignatureAlgoritmIdentifier.DeepChild(0, 0).Verify(OID.ToByteArray(OID.OIDcontentType)); //Verify that node 0.0 is a OIDcontentType Object identifier SignatureAlgoritmIdentifier.DeepChild(0, 1, 0).Verify(OID.ToByteArray(OID.OIDldsSecurityObject)); //Verify that node 0.1.0 is a OIDldsSecurityObject Object identifier SignatureAlgoritmIdentifier.DeepChild(1, 0).Verify(OID.ToByteArray(OID.OIDmessageDigest)); //Verify that node 1.0 is a OIDmessageDigest Object identifier //Get message digest of Signer that is in the octect string object SignerMessageDigest = SignatureAlgoritmIdentifier.DeepChild(1, 1).Child(0, 04); //04 Verify that result is a OCTECT STRING //GET MESSAGE DIGEST SIGN ALGORYTM AND HASH ALGORYTM OIDDSMessageDigestSignAlgo = OID.ToString(signerInfo.DeepChild(4).Child(0, 06).Data); //06 Verify that result is a OBJECT IDENTIFIER OIDDSMessageDigestHashAlgo = OID.ToString(signerInfo.DeepChild(2).Child(0, 06).Data); //06 Verify that result is a OBJECT IDENTIFIER //Verify Signed data hash algoritm //SignedData.Child(0, 02).Verify(new byte[] { 0 }); SignedData.DeepChild(1).Child(0, 06).Verify(OID.Encode(OIDDSMessageDigestHashAlgo)); //Verify hash algoritm /*GET SIGNATURE * La struttura dati contenuta si avvicina alla seguente: * 0 OCTET STRING (42C600B32BD5EFF0A684F65BD4526872AD3D4EADA3017A6E836736340BCCDA7DB9622...)*/ Signature = signerInfo.Child(5, 04); //04 Verify that result is a OCTECT STRING }
public bool Verify(byte[] nis) { var digestAlgo = string.Empty; switch (OIDDSMessageDigestHashAlgo) { case "2.16.840.1.101.3.4.2.1": digestAlgo = "SHA256"; break; case "2.16.840.1.101.3.4.2.3": digestAlgo = "SHA512"; break; default: throw new Exception("hash algoritm not valid"); } /*Get hashed data of * - ID servizi * - Seriale carta * - Certificato utente * - Chiave pubblica di internal authentication * - Chiave pubblica di internal authentication per i servizi * contained in SignedDataObject and calculate hash of hash*/ var digestRecalculation = SignedDataObject.DeepChild(1, 0).Data.ToMessageDigest(digestAlgo); //Compare recalculation of hash with data contained in signer message digest object to verify equality if (digestRecalculation.ToHexString() != SignerMessageDigest.Data.ToHexString()) { return(false); // Digest SOD not correspond to data } //Get Document Signer public key from SignedCert data var dsPubKey = DSCertificate.DeepChild(0, 6, 1, 0); //Get modulus and exponent from Document Signer public key var dsModPubKey = dsPubKey.Child(0, 0x02).Data; // modulus. 0x02 Verify that result is a INTEGER var dsExpPubKey = dsPubKey.Child(1, 0x02).Data; // exp. 0x02 Verify that result is a INTEGER //Verify SOD sign using DS public key and sign algoritm using (var rsa = new RSAService(dsModPubKey, dsExpPubKey)) { var isValidSod = false; switch (OIDDSMessageDigestSignAlgo) { case "1.2.840.113549.1.1.5": isValidSod = rsa.CheckSHA1withRSAEncryption(Signature.Data, SignatureAlgoritmIdentifier.MakeTag(0x31)); break; case "1.2.840.113549.1.1.10": isValidSod = rsa.CheckRSASSAPSS(Signature.Data, SignatureAlgoritmIdentifier.MakeTag(0x31), digestAlgo); break; default: throw new Exception("Sign aloritm not supported"); } if (!isValidSod) { throw new Exception("SOD sign wrong"); //SOD sign wrong } } //Get issuer information from Document Signer certificate and compare it with data in IssuerName ASN1 tag var issuer = DSCertificate.DeepChild(0).Child(3, 0x30); //0x30 Verify that result is a SEQUENCE //Compare issuer information obtained from DS certificate with information stored directly in IssuerName tag if (issuer.Data.ToHexString() != IssuerName.Data.ToHexString()) { return(false); //Issuer name check failed } //Get serial number information from Document Signer certificate and compare it with data in SignerCertSerialNumber ASN1 tag var serialNumber = DSCertificate.DeepChild(0).Child(1, 0x02); //02 Verify that result is a INTEGER if (serialNumber.Data.ToHexString() != SerialNumber.Data.ToHexString()) { return(false); // Serial Number of certificate wrong } //Get hash of NIS and verify it with NIS stored in file system var dgsHash = SignedData.Child(2, 0x30); //0x30 Verify that result is a SEQUENCE var isValidNis = false; foreach (var dg in dgsHash.children) { /* * 0xa1 : IdServizi * 0xa2 : Seriale carta * 0xa3 : Certificato utente * 0xa4 : Chiave pubblica di Internal Authentication * 0xa5 : Chiave pubblica di Internal Authentication per i Servizi * 0x1b : Parametri DH */ var oID = dg.Child(0, 02); //02 Verify that result is a INTEGER if (oID.Data.ToHexString() == "a1") { //Get hashed NIS from DG var hashedNis = dg.Child(1, 04).Data; //04 Verify that result is a OCTECT STRING //Calculate hash of file nis and compare it with the other in dg if (hashedNis.ToHexString() == nis.ToMessageDigest(digestAlgo).ToHexString()) { isValidNis = true; } } } //TODO: Check that certificate is issued by https://csca-ita.interno.gov.it/index_ITA.htm (CSCA certificate) return(isValidNis); }