// (c) 2006 Richard Grimes // www.grimes.demon.co.uk using System; using System.Security.Cryptography.Pkcs; using System.Security.Cryptography.X509Certificates; using System.IO; using System.Text; class App { // Command line params: s|v infile outfile certname static void Main(string[] args) { if (args.Length < 3) { Console.WriteLine("Usage: signer s|v infile [certname]"); return; } bool sign = true; sign = (args[0].ToLower()[0] == 's'); string infile = args[1]; if (!File.Exists(infile)) { Console.WriteLine("{0} does not exist", infile); return; } if (sign) { string certname = args[2]; X509Certificate2 cert = GetCertificate(certname); if (cert == null) { Console.WriteLine("No certificate with the name {0}", certname); return; } // outfile should be given only if you are signing string outfile = null; outfile = Path.GetFileNameWithoutExtension(infile) + ".p7s"; if (File.Exists(outfile)) { File.Delete(outfile); } SignMsg(infile, outfile, cert); } else { if (VerifyMsg(infile)) { Console.WriteLine("\nMessage verified"); } else { Console.WriteLine("\nMessage failed to verify"); } } } static X509Certificate2 GetCertificate(string certname) { X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser); store.Open(OpenFlags.ReadOnly); // Find the signer's certificate. X509Certificate2Collection certs = store.Certificates.Find(X509FindType.FindBySubjectName, certname, false); store.Close(); if (certs.Count == 0) { return null; } return certs[0]; } static void SignMsg(string infile, string outfile, X509Certificate2 cert) { ContentInfo contentInfo = null; using (FileStream fsIn = File.OpenRead(infile)) { int count = (int)fsIn.Length; byte[] data = new byte[count]; int read = 0; int offset = 0; while (count > 0) { read = fsIn.Read(data, offset, count); if (read == 0) break; offset += read; count -= read; } contentInfo = new ContentInfo(data); } // The signature and message are encoded together SignedCms signedCms = new SignedCms(contentInfo); CmsSigner cmsSigner = new CmsSigner(cert); signedCms.ComputeSignature(cmsSigner); byte[] enc = signedCms.Encode(); using (FileStream fsOut = File.OpenWrite(outfile)) { fsOut.Write(enc, 0, enc.Length); } } static bool VerifyMsg(string infile) { byte[] data = null; using (FileStream fsIn = File.OpenRead(infile)) { int count = (int)fsIn.Length; data = new byte[count]; int read = 0; int offset = 0; while (count > 0) { read = fsIn.Read(data, offset, count); if (read == 0) break; offset += read; count -= read; } } SignedCms signedCms = new SignedCms(); signedCms.Decode(data); try { signedCms.CheckSignature(true); } catch (System.Security.Cryptography.CryptographicException) { return false; } return true; } }