diff options
author | Sebastien Pouliot <sebastien@ximian.com> | 2003-09-02 04:00:09 +0400 |
---|---|---|
committer | Sebastien Pouliot <sebastien@ximian.com> | 2003-09-02 04:00:09 +0400 |
commit | e3c3cb1a3b19119b3e207359cf062b3c87e5ca9e (patch) | |
tree | 53a81a0674656295f4fb86d5dcfca4741ce673c1 /mcs/class/Mono.Security/Mono.Security.Authenticode | |
parent | 72e5383d31d86e17775b64593fc9dadfa998c303 (diff) |
2003-09-01 Sebastien Pouliot <spouliot@videotron.ca>
* AuthenticodeBase.cs: New. Base class including how to hash a
PE file.
* AuthenticodeDeformatter.cs: New. Class to decode Authenticode(tm)
signatures.
* AuthenticodeFormatter.cs: New. Class to encode a Authenticode(tm)
signature, and optionally a timestamp, into a PE file.
* SoftwarePublisherCertificate.cs: Now use Mono.Security.X509.
X509Certificate class.
svn path=/trunk/mcs/; revision=17810
Diffstat (limited to 'mcs/class/Mono.Security/Mono.Security.Authenticode')
5 files changed, 760 insertions, 1 deletions
diff --git a/mcs/class/Mono.Security/Mono.Security.Authenticode/AuthenticodeBase.cs b/mcs/class/Mono.Security/Mono.Security.Authenticode/AuthenticodeBase.cs new file mode 100755 index 00000000000..d46d0f3e86c --- /dev/null +++ b/mcs/class/Mono.Security/Mono.Security.Authenticode/AuthenticodeBase.cs @@ -0,0 +1,86 @@ +// +// AuthenticodeBase.cs: Authenticode signature base class +// +// Author: +// Sebastien Pouliot (spouliot@motus.com) +// +// (C) 2003 Motus Technologies Inc. (http://www.motus.com) +// + +using System; +using System.IO; +using System.Security.Cryptography; + +namespace Mono.Security.Authenticode { + + // References: + // a. http://www.cs.auckland.ac.nz/~pgut001/pubs/authenticode.txt + + public enum Authority { + Individual, + Commercial, + Maximum + } + + public class AuthenticodeBase { + + public const string spcIndirectDataContext = "1.3.6.1.4.1.311.2.1.4"; + + protected byte[] rawData; + + public AuthenticodeBase () {} + + protected byte[] HashFile (string fileName, string hashName) + { + FileStream fs = new FileStream (fileName, FileMode.Open, FileAccess.Read, FileShare.Read); + byte[] file = new byte [fs.Length]; + fs.Read (file, 0, file.Length); + fs.Close (); + + // MZ - DOS header + if (BitConverter.ToUInt16 (file, 0) != 0x5A4D) + return null; + + // find offset of PE header + int peOffset = BitConverter.ToInt32 (file, 60); + if (peOffset > file.Length) + return null; + + // PE - NT header + if (BitConverter.ToUInt16 (file, peOffset) != 0x4550) + return null; + + // IMAGE_DIRECTORY_ENTRY_SECURITY + int dirSecurityOffset = BitConverter.ToInt32 (file, peOffset + 152); + int dirSecuritySize = BitConverter.ToInt32 (file, peOffset + 156); + + if (dirSecuritySize > 8) { + rawData = new byte [dirSecuritySize - 8]; + Array.Copy (file, dirSecurityOffset + 8, rawData, 0, rawData.Length); +/* DEBUG + FileStream debug = new FileStream (fileName + ".sig", FileMode.Create, FileAccess.Write); + debug.Write (rawData, 0, rawData.Length); + debug.Close ();*/ + } + else + rawData = null; + + HashAlgorithm hash = HashAlgorithm.Create (hashName); + // 0 to 215 (216) then skip 4 (checksum) + int pe = peOffset + 88; + hash.TransformBlock (file, 0, pe, file, 0); + pe += 4; + // 220 to 279 (60) then skip 8 (IMAGE_DIRECTORY_ENTRY_SECURITY) + hash.TransformBlock (file, pe, 60, file, pe); + pe += 68; + // 288 to end of file + int n = file.Length - pe; + // minus any authenticode signature (with 8 bytes header) + if (dirSecurityOffset != 0) + n -= (dirSecuritySize); + hash.TransformFinalBlock (file, pe, n); + + return hash.Hash; + } + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Authenticode/AuthenticodeDeformatter.cs b/mcs/class/Mono.Security/Mono.Security.Authenticode/AuthenticodeDeformatter.cs new file mode 100755 index 00000000000..26d4f928ed7 --- /dev/null +++ b/mcs/class/Mono.Security/Mono.Security.Authenticode/AuthenticodeDeformatter.cs @@ -0,0 +1,365 @@ +// +// AuthenticodeSignature.cs: Authenticode signature validator and generator +// +// Author: +// Sebastien Pouliot (spouliot@motus.com) +// +// (C) 2003 Motus Technologies Inc. (http://www.motus.com) +// + +using System; +using System.IO; +using System.Security.Cryptography; + +using Mono.Security; +using Mono.Security.X509; + +namespace Mono.Security.Authenticode { + + // References: + // a. http://www.cs.auckland.ac.nz/~pgut001/pubs/authenticode.txt + + public class AuthenticodeDeformatter : AuthenticodeBase { + + private string filename; + private byte[] hash; + private X509CertificateCollection coll; + private ASN1 signedHash; + private DateTime timestamp; + private X509Certificate signingCertificate; + private int reason; + + private X509Chain signerChain; + private X509Chain timestampChain; + + public AuthenticodeDeformatter () : base () + { + reason = -1; + signerChain = new X509Chain (); + timestampChain = new X509Chain (); + } + + public AuthenticodeDeformatter (string fileName) : this () + { + CheckSignature (fileName); + } + + public string FileName { + get { return filename; } + set { CheckSignature (value); } + } + + public byte[] Hash { + get { + if (signedHash == null) + return null; + return signedHash.Value; + } + } + + public int Reason { + get { + if (reason == -1) + IsTrusted (); + return reason; + } + } + + public bool IsTrusted () + { + if (rawData == null) { + reason = 1; + return false; + } + + if (signingCertificate == null) { + reason = 7; + return false; + } + + if (signerChain.Root == null) { + reason = 6; + return false; + } + + if (timestamp != DateTime.MinValue) { + if (timestampChain.Root == null) { + reason = 6; + return false; + } + + // check that file was timestamped when certificates were valid + if (!signingCertificate.WasCurrent (Timestamp)) { + reason = 4; + return false; + } + } + else if (!signingCertificate.IsCurrent) { + // signature only valid if the certificate is valid + reason = 8; + return false; + } + + reason = 0; + return true; + } + + public byte[] Signature { + get { return rawData; } + } + + public DateTime Timestamp { + get { return timestamp; } + } + + public X509CertificateCollection Certificates { + get { return coll; } + } + + private bool CheckSignature (string fileName) + { + filename = fileName; + + // by default we try with MD5 + string hashName = "MD5"; + // compare the signature's hash with the hash of the file + hash = HashFile (filename, hashName); + + // is a signature present ? + if (rawData == null) + return false; + + PKCS7.ContentInfo ci = new PKCS7.ContentInfo (rawData); + if (ci.ContentType != PKCS7.signedData) + return false; + + PKCS7.SignedData sd = new PKCS7.SignedData (ci.Content); + if (sd.ContentInfo.ContentType != spcIndirectDataContext) + return false; + + coll = sd.Certificates; + + ASN1 spc = sd.ContentInfo.Content; + signedHash = spc [0][1][1]; + if (signedHash.Length == 20) { + // seems to be SHA-1, restart hashing + hashName = "SHA1"; + hash = HashFile (filename, hashName); + } + + if (!signedHash.CompareValue (hash)) + return false; + + // messageDigest is a hash of spcIndirectDataContext (which includes the file hash) + byte[] spcIDC = spc [0].Value; + HashAlgorithm ha = HashAlgorithm.Create (hashName); + byte[] messageDigest = ha.ComputeHash (spcIDC); + + return VerifySignature (sd, messageDigest, hashName); + } + + private bool CompareIssuerSerial (string issuer, byte[] serial, X509Certificate x509) + { + if (issuer != x509.IssuerName) + return false; + if (serial.Length != x509.SerialNumber.Length) + return false; + // MS shows the serial number inversed (so is Mono.Security.X509.X509Certificate) + int n = serial.Length; + for (int i=0; i < serial.Length; i++) { + if (serial [i] != x509.SerialNumber [--n]) + return false; + } + // must be true + return true; + } + + //private bool VerifySignature (ASN1 cs, byte[] calculatedMessageDigest, string hashName) + private bool VerifySignature (PKCS7.SignedData sd, byte[] calculatedMessageDigest, string hashName) + { + 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][1][0].Value); + } + catch { + 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 (hashName); + + // 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); + HashAlgorithm ha = HashAlgorithm.Create (hashName); + 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)) { + RSACryptoServiceProvider rsa = (RSACryptoServiceProvider) x509.RSA; + if (rsa.VerifyHash (p7hash, hashOID, signature)) { + signerChain.LoadCertificates (coll); + if (signerChain.GetChain (x509) != null) + signingCertificate = x509; + else + return false; + } + } + } + } + + 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.countersignature: + // SEQUENCE { + // OBJECT IDENTIFIER + // countersignature (1 2 840 113549 1 9 6) + // SET { + PKCS7.SignerInfo cs = new PKCS7.SignerInfo (attr [1]); + return VerifyCounterSignature (cs, signature, hashName); + default: + // we don't support other unauthenticated attributes + break; + } + } + + return true; + } + + //private bool VerifyCounterSignature (ASN1 cs, byte[] signature, string hashName) + private bool VerifyCounterSignature (PKCS7.SignerInfo cs, byte[] signature, string hashName) + { + // 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.data) + return false; + + // verify message digest + if (messageDigest == null) + return false; + // TODO: must be read from the ASN.1 structure + 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 is 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.GetChain (x509) != null); + } + } + } + } + // no certificate can verify this signature! + return false; + } + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Authenticode/AuthenticodeFormatter.cs b/mcs/class/Mono.Security/Mono.Security.Authenticode/AuthenticodeFormatter.cs new file mode 100755 index 00000000000..1410cc88f62 --- /dev/null +++ b/mcs/class/Mono.Security/Mono.Security.Authenticode/AuthenticodeFormatter.cs @@ -0,0 +1,297 @@ +// +// AuthenticodeFormatter.cs: Authenticode signature generator +// +// Author: +// Sebastien Pouliot (spouliot@motus.com) +// +// (C) 2003 Motus Technologies Inc. (http://www.motus.com) +// + +using System; +using System.Collections; +using System.IO; +using System.Security.Cryptography; +//using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Net; + +using Mono.Security; +using Mono.Security.X509; + +namespace Mono.Security.Authenticode { + + public class AuthenticodeFormatter : AuthenticodeBase { + + private Authority authority; + private X509CertificateCollection certs; + private ArrayList crls; + private string hash; + private RSA rsa; + private string timestamp; + private ASN1 authenticode; + private PKCS7.SignedData pkcs7; + private string description; + private string url; + + public AuthenticodeFormatter () : base () + { + certs = new X509CertificateCollection (); + crls = new ArrayList (); + authority = Authority.Maximum; + pkcs7 = new PKCS7.SignedData (); + } + + public Authority Authority { + get { return authority; } + set { authority = value; } + } + + public X509CertificateCollection Certificates { + get { return certs; } + } + + public ArrayList CRL { + get { return crls; } + } + + public string Hash { + get { + if (hash == null) + hash = "MD5"; + return hash; + } + set { + string h = value.ToUpper (); + if ((h == "MD5") || (hash == "SHA1")) + hash = value; + else + throw new ArgumentException ("Invalid Authenticode hash algorithm"); + } + } + + public RSA RSA { + get { return rsa; } + set { rsa = value; } + } + + public string TimestampURL { + get { return timestamp; } + set { timestamp = value; } // URL + } + + public string Description { + get { return description; } + set { description = value; } + } + + public string URL { + get { return url; } + set { url = value; } // URL + } + + private ASN1 AlgorithmIdentifier (string oid) + { + ASN1 ai = new ASN1 (0x30); + ai.Add (ASN1Convert.FromOID (oid)); + ai.Add (new ASN1 (0x05)); // NULL + return ai; + } + + private ASN1 Attribute (string oid, ASN1 value) + { + ASN1 attr = new ASN1 (0x30); + attr.Add (ASN1Convert.FromOID (oid)); + ASN1 aset = attr.Add (new ASN1 (0x31)); + aset.Add (value); + return attr; + } + + private ASN1 Opus (string description, string url) + { + ASN1 opus = new ASN1 (0x30); + if (description != null) { + ASN1 part1 = opus.Add (new ASN1 (0xA0)); + part1.Add (new ASN1 (0x80, Encoding.BigEndianUnicode.GetBytes (description))); + } + if (url != null) { + ASN1 part2 = opus.Add (new ASN1 (0xA1)); + part2.Add (new ASN1 (0x80, Encoding.ASCII.GetBytes (url))); + } + return opus; + } + + // pkcs 1 + private const string rsaEncryption = "1.2.840.113549.1.1.1"; + // pkcs 7 + private const string data = "1.2.840.113549.1.7.1"; + private const string signedData = "1.2.840.113549.1.7.2"; + // pkcs 9 + private const string contentType = "1.2.840.113549.1.9.3"; + private const string messageDigest = "1.2.840.113549.1.9.4"; + private const string countersignature = "1.2.840.113549.1.9.6"; + // microsoft spc (software publisher certificate) + private const string spcStatementType = "1.3.6.1.4.1.311.2.1.11"; + private const string spcSpOpusInfo = "1.3.6.1.4.1.311.2.1.12"; + private const string spcPelmageData = "1.3.6.1.4.1.311.2.1.15"; + private const string individualCodeSigning = "1.3.6.1.4.1.311.2.1.21"; + private const string commercialCodeSigning = "1.3.6.1.4.1.311.2.1.22"; + private const string timestampCountersignature = "1.3.6.1.4.1.311.3.2.1"; + + private static byte[] version = { 0x01 }; + private static byte[] obsolete = { 0x03, 0x01, 0x00, 0xA0, 0x20, 0xA2, 0x1E, 0x80, 0x1C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x4F, 0x00, 0x62, 0x00, 0x73, 0x00, 0x6F, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x74, 0x00, 0x65, 0x00, 0x3E, 0x00, 0x3E, 0x00, 0x3E }; + + private byte[] Header (byte[] fileHash, string hashAlgorithm) + { + string hashOid = CryptoConfig.MapNameToOID (hashAlgorithm); + ASN1 content = new ASN1 (0x30); + ASN1 c1 = content.Add (new ASN1 (0x30)); + c1.Add (ASN1Convert.FromOID (spcPelmageData)); + c1.Add (new ASN1 (0x30, obsolete)); + ASN1 c2 = content.Add (new ASN1 (0x30)); + c2.Add (AlgorithmIdentifier (hashOid)); + c2.Add (new ASN1 (0x04, fileHash)); + + pkcs7.HashName = hashAlgorithm; + pkcs7.Certificates.AddRange (certs); + pkcs7.ContentInfo.ContentType = spcIndirectDataContext; + pkcs7.ContentInfo.Content.Add (content); + + pkcs7.SignerInfo.Certificate = certs [0]; + pkcs7.SignerInfo.Key = rsa; + pkcs7.SignerInfo.AuthenticatedAttributes.Add (Attribute (spcSpOpusInfo, Opus (description, url))); + pkcs7.SignerInfo.AuthenticatedAttributes.Add (Attribute (contentType, ASN1Convert.FromOID (spcIndirectDataContext))); + pkcs7.SignerInfo.AuthenticatedAttributes.Add (Attribute (spcStatementType, new ASN1 (0x30, ASN1Convert.FromOID (commercialCodeSigning).GetBytes ()))); + + ASN1 temp = pkcs7.ASN1; // sign + return pkcs7.SignerInfo.Signature; + } + + public ASN1 TimestampRequest (byte[] signature) + { + PKCS7.ContentInfo ci = new PKCS7.ContentInfo (PKCS7.data); + ci.Content.Add (new ASN1 (0x04, signature)); + return PKCS7.AlgorithmIdentifier (timestampCountersignature, ci.ASN1); + } + + public void ProcessTimestamp (byte[] tsres) + { + ASN1 ts = new ASN1 (Convert.FromBase64String (Encoding.ASCII.GetString (tsres))); + // first validate the received message + // TODO + + // add the supplied certificates inside our signature + for (int i=0; i < ts[1][0][3].Count; i++) + pkcs7.Certificates.Add (new X509Certificate (ts[1][0][3][i].GetBytes ())); + + // add an unauthentified attribute to our signature + pkcs7.SignerInfo.UnauthenticatedAttributes.Add (Attribute (countersignature, ts[1][0][4][0])); + } + + public bool Sign (string fileName) + { + string hashAlgorithm = "MD5"; + FileStream fs = new FileStream (fileName, FileMode.Open, FileAccess.Read, FileShare.Read); + byte[] file = new byte [fs.Length]; + fs.Read (file, 0, file.Length); + fs.Close (); + + // MZ - DOS header + if (BitConverter.ToUInt16 (file, 0) != 0x5A4D) + return false; + + // find offset of PE header + int peOffset = BitConverter.ToInt32 (file, 60); + if (peOffset > file.Length) + return false; + + // PE - NT header + if (BitConverter.ToUInt16 (file, peOffset) != 0x4550) + return false; + + // IMAGE_DIRECTORY_ENTRY_SECURITY + int dirSecurityOffset = BitConverter.ToInt32 (file, peOffset + 152); + int dirSecuritySize = BitConverter.ToInt32 (file, peOffset + 156); + + if (dirSecuritySize > 8) { + rawData = new byte [dirSecuritySize - 8]; + Array.Copy (file, dirSecurityOffset + 8, rawData, 0, rawData.Length); + } + else + rawData = null; + + HashAlgorithm hash = HashAlgorithm.Create (hashAlgorithm); + // 0 to 215 (216) then skip 4 (checksum) + int pe = peOffset + 88; + hash.TransformBlock (file, 0, pe, file, 0); + pe += 4; + // 220 to 279 (60) then skip 8 (IMAGE_DIRECTORY_ENTRY_SECURITY) + hash.TransformBlock (file, pe, 60, file, pe); + pe += 68; + // 288 to end of file + int n = file.Length - pe; + // minus any authenticode signature (with 8 bytes header) + if (dirSecurityOffset != 0) + n -= (dirSecuritySize); + hash.TransformFinalBlock (file, pe, n); + + // + byte[] signature = Header (hash.Hash, hashAlgorithm); + if (timestamp != null) { + ASN1 tsreq = TimestampRequest (signature); + WebClient wc = new WebClient (); + wc.Headers.Add ("Content-Type", "application/octet-stream"); + wc.Headers.Add ("Accept", "application/octet-stream"); + byte[] tsdata = Encoding.ASCII.GetBytes (Convert.ToBase64String (tsreq.GetBytes ())); + byte[] tsres = wc.UploadData (timestamp, tsdata); + ProcessTimestamp (tsres); + } + PKCS7.ContentInfo sign = new PKCS7.ContentInfo (signedData); + sign.Content.Add (pkcs7.ASN1); + authenticode = sign.ASN1; + + // debug + fs = File.Open (fileName + ".sig", FileMode.Create, FileAccess.Write); + byte[] asn = authenticode.GetBytes (); + fs.Write (asn, 0, asn.Length); + fs.Close (); + + File.Copy (fileName, fileName + ".bak", true); + + fs = File.Open (fileName, FileMode.Create, FileAccess.Write); + // IMAGE_DIRECTORY_ENTRY_SECURITY (offset, size) + byte[] data = BitConverter.GetBytes (file.Length); + file [peOffset + 152] = data [0]; + file [peOffset + 153] = data [1]; + file [peOffset + 154] = data [2]; + file [peOffset + 155] = data [3]; + int size = asn.Length + 8; + // must be a multiple of 8 bytes + int addsize = (size % 8); + if (addsize > 0) + addsize = 8 - addsize; + size += addsize; + data = BitConverter.GetBytes (size); // header + file [peOffset + 156] = data [0]; + file [peOffset + 157] = data [1]; + file [peOffset + 158] = data [2]; + file [peOffset + 159] = data [3]; + fs.Write (file, 0, file.Length); + fs.Write (data, 0, data.Length); // length (again) + data = BitConverter.GetBytes (0x00020200); // magic + fs.Write (data, 0, data.Length); + fs.Write (asn, 0, asn.Length); + // fill up + byte[] fillup = new byte [addsize]; + fs.Write (fillup, 0, fillup.Length); + fs.Close (); + + return true; + } + + // in case we just want to timestamp the file + public bool Timestamp (string fileName) + { + return true; + } + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Authenticode/ChangeLog b/mcs/class/Mono.Security/Mono.Security.Authenticode/ChangeLog index 0acf2ed937c..caa31ff19ff 100644 --- a/mcs/class/Mono.Security/Mono.Security.Authenticode/ChangeLog +++ b/mcs/class/Mono.Security/Mono.Security.Authenticode/ChangeLog @@ -1,3 +1,14 @@ +2003-09-01 Sebastien Pouliot <spouliot@videotron.ca> + + * AuthenticodeBase.cs: New. Base class including how to hash a + PE file. + * AuthenticodeDeformatter.cs: New. Class to decode Authenticode(tm) + signatures. + * AuthenticodeFormatter.cs: New. Class to encode a Authenticode(tm) + signature, and optionally a timestamp, into a PE file. + * SoftwarePublisherCertificate.cs: Now use Mono.Security.X509. + X509Certificate class. + 2003-06-19 Nick Drochak <ndrochak@gol.com> * PrivateKey.cs: Work around for mcs? bug 45127. diff --git a/mcs/class/Mono.Security/Mono.Security.Authenticode/SoftwarePublisherCertificate.cs b/mcs/class/Mono.Security/Mono.Security.Authenticode/SoftwarePublisherCertificate.cs index f7bd219bf63..0c7026b2519 100644 --- a/mcs/class/Mono.Security/Mono.Security.Authenticode/SoftwarePublisherCertificate.cs +++ b/mcs/class/Mono.Security/Mono.Security.Authenticode/SoftwarePublisherCertificate.cs @@ -11,9 +11,9 @@ using System; using System.Collections; using System.IO; -using System.Security.Cryptography.X509Certificates; using Mono.Security; +using Mono.Security.X509; namespace Mono.Security.Authenticode { |