public DSIGInfo(string filename) { fontfile = new OTFile(); tDSIG = null; Warn_TTCv1 = false; Warn_DSIG_in_memFonts = false; Warn_MalformedSIG = false; usNumSigs = 0; if (!fontfile.open(filename)) { throw new IOException("Cannot open file " + filename); } TTCHeader ttc = null; if (fontfile.IsCollection()) { ttc = fontfile.GetTTCHeader(); if (fontfile.GetTableManager().GetUnaliasedTableName(ttc.DsigTag) == "DSIG") { MBOBuffer buf = fontfile.ReadPaddedBuffer(ttc.DsigOffset, ttc.DsigLength); tDSIG = (Table_DSIG)fontfile.GetTableManager().CreateTableObject(ttc.DsigTag, buf); } for (uint i = 0; i < fontfile.GetNumFonts(); i++) { OTFont fn = fontfile.GetFont(i); Table_DSIG memDSIG = (Table_DSIG)fn.GetTable("DSIG"); if (memDSIG != null) { Warn_DSIG_in_memFonts = true; break; } } } else { OTFont fn = fontfile.GetFont(0); tDSIG = (Table_DSIG)fn.GetTable("DSIG"); } HaveDSIG = ((tDSIG == null) ? false : true); // Officially we should only warn if HaveDSIG true if (fontfile.IsCollection() && ttc.version != 0x00020000) { Warn_TTCv1 = true; } if (HaveDSIG) { FurtherWork(); } }
static int Main(string[] args) { if (args.Length == 0) { Console.WriteLine("DSIGInfo [-v] [-v] [-v] fontfile"); return(0); } OTFile f = new OTFile(); Table_DSIG tDSIG = null; string filename = null; verbose = 0; for (int i = 0; i < args.Length; i++) { if ("-v" == args[i]) { verbose++; } else { filename = args[i]; } } if (!f.open(filename)) { Console.WriteLine("Error: Cannot open {0} as font file", filename); return(0); } TTCHeader ttc = null; if (f.IsCollection()) { ttc = f.GetTTCHeader(); if (f.GetTableManager().GetUnaliasedTableName(ttc.DsigTag) == "DSIG") { MBOBuffer buf = f.ReadPaddedBuffer(ttc.DsigOffset, ttc.DsigLength); tDSIG = (Table_DSIG)f.GetTableManager().CreateTableObject(ttc.DsigTag, buf); } for (uint i = 0; i < f.GetNumFonts(); i++) { OTFont fn = f.GetFont(i); Table_DSIG memDSIG = (Table_DSIG)fn.GetTable("DSIG"); if (memDSIG != null) { Console.WriteLine("Warning: DSIG in member font"); break; } } } else { OTFont fn = f.GetFont(0); tDSIG = (Table_DSIG)fn.GetTable("DSIG"); } Console.WriteLine("{0} DSIG table: {1}", filename, (tDSIG == null) ? "Absent" : "Present"); if (tDSIG == null) { return(0); } if (f.IsCollection() && ttc.version != 0x00020000) { Console.WriteLine("Warning: TTC has DSIG but header version is 0x{0}, != 0x00020000", ttc.version.ToString("X8")); } if (tDSIG.usNumSigs != 1) { Console.WriteLine("NumSigs = {0}", tDSIG.usNumSigs); } for (uint v = 0; v < tDSIG.usNumSigs; v++) { Table_DSIG.SignatureBlock sgb; try { sgb = tDSIG.GetSignatureBlock(v); } catch (IndexOutOfRangeException) { Console.WriteLine("Error: Out of Range SignatureBlock {0}", v); break; } SignedCms cms = new SignedCms(); try { cms.Decode(sgb.bSignature); } catch (Exception e) { if (e is NullReferenceException || /* Mono */ e is CryptographicException /* .Net2 */) { Console.WriteLine("Error: Malformed Signature"); break; } Console.WriteLine("Error: Malformed Signature (Unexpected Case 1)"); throw; } if (cms.SignerInfos.Count > 1) { Console.WriteLine("#SignerInfos: {0}", cms.SignerInfos.Count); } foreach (var si in cms.SignerInfos) { Console.WriteLine(si.Certificate); if (Type.GetType("Mono.Runtime") == null) { foreach (var ua in si.UnsignedAttributes) { foreach (var asnd in ua.Values) { try { ASN1 vv = new ASN1(asnd.RawData); ASN1 t = new ASN1(vv[3][1][1].Value); Console.WriteLine("Decoded Signing Time: {0}", ASN1Convert.ToDateTime(t)); } catch (Exception) { /* Nothing to do */ } } } } } Console.WriteLine("#Certificates: {0}", cms.Certificates.Count); #if HAVE_MONO_X509 certs = new Mono.Security.X509.X509CertificateCollection(); //Mono.Security.X509.X509Chain signerChain = new Mono.Security.X509.X509Chain (); #endif foreach (var x509 in cms.Certificates) { #if HAVE_MONO_X509 certs.Add(new Mono.Security.X509.X509Certificate(x509.RawData)); #endif if (verbose > 0) { Console.WriteLine(x509); } else { Console.WriteLine(x509.Subject); } } ; #if HAVE_MONO_X509 Mono.Security.X509.X509Certificate x = new Mono.Security.X509.X509Certificate(cms.SignerInfos[0].Certificate.RawData); Mono.Security.X509.X509Certificate parent = x; while (x != null) // Self-signed is fine - the font bundled CA is self-signed. { parent = x; // last valid x = FindCertificateParent(x); if (x != null && x.Equals(parent)) { break; } } #endif // Windows 10/.net 4.6.x throws here ASN1 spc; try { spc = new ASN1(cms.ContentInfo.Content); } catch (Exception e) { if (e is IndexOutOfRangeException) { Console.WriteLine("Error: Malformed Signature (Win10/.net 4.6.x)"); break; } Console.WriteLine("Error: Malformed Signature (Unexpected Case 2)"); throw; } ASN1 playload_oid = null; ASN1 oid = null; ASN1 digest = null; ASN1 obsolete = null; if (Type.GetType("Mono.Runtime") == null) { // DotNet is much saner! playload_oid = spc[0][0]; obsolete = spc[0][1][0]; oid = spc[1][0][0]; digest = spc[1][1]; } else { playload_oid = spc[0]; obsolete = spc[1][0]; oid = spc[2][0][0]; digest = spc[2][1]; } string algo = ASN1Convert.ToOid(oid); string algoname = (new Oid(algo)).FriendlyName; Console.WriteLine("Digest Algorithm: {0}", algoname); byte[] Value = digest.Value; StringBuilder hexLine_sig = new StringBuilder(); for (int i = 0; i < Value.Length; i++) { hexLine_sig.AppendFormat("{0} ", Value [i].ToString("X2")); } hexLine_sig.AppendFormat(Environment.NewLine); switch (algoname) { case "md5": hash = HashAlgorithm.Create("MD5"); break; case "sha1": hash = HashAlgorithm.Create("SHA1"); break; default: throw new NotImplementedException("Unknown HashAlgorithm: " + algoname); } byte[] cdigest; if (f.IsCollection()) { cdigest = get_TTC_digest(f); } else { cdigest = get_TTF_digest(f); } StringBuilder hexLine = new StringBuilder(); for (int i = 0; i < cdigest.Length; i++) { hexLine.AppendFormat("{0} ", cdigest [i].ToString("X2")); } hexLine.AppendFormat(Environment.NewLine); Console.WriteLine("{0} Signed Digest:\t{1}", algoname.ToUpper(), hexLine_sig); Console.WriteLine("Calculated Digest:\t{0}", hexLine); string root_thumb = ""; #if HAVE_MONO_X509 root_thumb = (new System.Security.Cryptography.X509Certificates.X509Certificate2(parent.RawData)).Thumbprint; Console.WriteLine("ChainEnd Name: {0}", parent.SubjectName); Console.WriteLine("ChainEnd Self-Signed: {0}", parent.IsSelfSigned); #endif Console.WriteLine("ChainEnd: {0}", root_thumb); bool trusted = false; try { string root_id = trusted_roots[root_thumb]; Console.WriteLine("RootID: {0}", root_id); trusted = true; } catch (KeyNotFoundException) {} Console.WriteLine("Trusted: {0}", trusted); } return(0); }
void FurtherWork() { usNumSigs = tDSIG.usNumSigs; if (tDSIG.usNumSigs > 1) { throw new NotImplementedException("usNumSigs=" + tDSIG.usNumSigs + " > 1"); } for (uint v = 0; v < tDSIG.usNumSigs; v++) { Table_DSIG.SignatureBlock sgb; try { sgb = tDSIG.GetSignatureBlock(v); } catch (IndexOutOfRangeException) { Warn_MalformedSIG = true; break; } SignedCms cms = new SignedCms(); try { cms.Decode(sgb.bSignature); } catch (Exception e) { if (e is NullReferenceException || /* Mono */ e is CryptographicException /* .Net2 */) { Warn_MalformedSIG = true; break; } throw; } signer_count = cms.SignerInfos.Count; if (signer_count > 1) { throw new NotImplementedException("SignerInfos.Count=" + signer_count + " > 1"); } foreach (var si in cms.SignerInfos) { signer = si.Certificate.Subject; } ; // Windows 10/.net 4.6.x throws here ASN1 spc; try { spc = new ASN1(cms.ContentInfo.Content); } catch (Exception e) { if (e is IndexOutOfRangeException) { Warn_MalformedSIG = true; break; } throw; } ASN1 playload_oid = null; ASN1 oid = null; ASN1 digest = null; ASN1 obsolete = null; if (Type.GetType("Mono.Runtime") == null) { // DotNet is much saner! playload_oid = spc[0][0]; obsolete = spc[0][1][0]; oid = spc[1][0][0]; digest = spc[1][1]; } else { playload_oid = spc[0]; obsolete = spc[1][0]; oid = spc[2][0][0]; digest = spc[2][1]; } string algo = ASN1Convert.ToOid(oid); algoname = (new Oid(algo)).FriendlyName; signed_hash = digest.Value; switch (algoname) { case "md5": hash = HashAlgorithm.Create("MD5"); break; case "sha1": hash = HashAlgorithm.Create("SHA1"); break; case "sha256": hash = HashAlgorithm.Create("SHA256"); break; case "sha384": hash = HashAlgorithm.Create("SHA384"); break; case "sha512": hash = HashAlgorithm.Create("SHA512"); break; default: throw new NotImplementedException("Unknown HashAlgorithm: " + algoname); } if (fontfile.IsCollection()) { calc_hash = get_TTC_digest(); } else { calc_hash = get_TTF_digest(); } } }