/// <summary> /// Intitializes class instance /// </summary> /// <param name="id">Hex encoded string with identifier (value of CKA_ID attribute) of the certificate</param> /// <param name="label">Label (value of CKA_LABEL attribute) of the certificate</param> /// <param name="data">DER encoded certificate data (value of CKA_VALUE attribute)</param> internal Certificate(string id, string label, byte[] data) { if (data == null) { throw new ArgumentNullException("data"); } BCX509.X509Certificate cert = CertUtils.ToBouncyCastleObject(data); _id = id; _label = label; _data = data; _publicKey = cert.GetPublicKey(); }
/// <summary> /// Main method specifying where program execution is to begin /// </summary> /// <param name="args">Command line arguments passed to the program</param> static void Main(string[] args) { try { // Parse command line arguments string pkcs11Library = null; int listTokens = 0; int listObjects = 0; int sign = 0; string tokenSerial = null; string tokenLabel = null; string pin = null; string keyLabel = null; string keyId = null; string dataFile = null; string signatureFile = null; string hashAlg = null; string signatureScheme = null; string outputFormat = null; string certsDir = null; if (args.Length == 0) { ExitWithHelp(null); } int i = 0; while (i < args.Length) { switch (args[i]) { case _argPkcs11Library: pkcs11Library = args[++i]; break; case _argListTokens: listTokens = 1; break; case _argListObjects: listObjects = 1; break; case _argSign: sign = 1; break; case _argTokenSerial: tokenSerial = args[++i]; break; case _argTokenLabel: tokenLabel = args[++i]; break; case _argPin: pin = args[++i]; break; case _argKeyLabel: keyLabel = args[++i]; break; case _argKeyId: keyId = args[++i]; break; case _argDataFile: dataFile = args[++i]; break; case _argSignatureFile: signatureFile = args[++i]; break; case _argHashAlg: hashAlg = args[++i]; break; case _argSignatureScheme: signatureScheme = args[++i]; break; case _argOutputFormat: outputFormat = args[++i]; break; case _argCertsDir: certsDir = args[++i]; break; default: ExitWithHelp("Invalid argument: " + args[i]); break; } i++; } // Validate operation modes if (listTokens + listObjects + sign != 1) { ExitWithHelp(string.Format("Argument \"{0}\", \"{1}\" or \"{2}\" has to be specified", _argListTokens, _argListObjects, _argSign)); } // Handle "--list-tokens" operation mode if (listTokens == 1) { // Validate command line arguments if (string.IsNullOrEmpty(pkcs11Library)) { ExitWithHelp("Required argument: " + _argPkcs11Library); } if (!string.IsNullOrEmpty(tokenSerial)) { ExitWithHelp("Unexpected argument: " + _argTokenSerial); } if (!string.IsNullOrEmpty(tokenLabel)) { ExitWithHelp("Unexpected argument: " + _argTokenLabel); } if (!string.IsNullOrEmpty(pin)) { ExitWithHelp("Unexpected argument: " + _argPin); } if (!string.IsNullOrEmpty(keyLabel)) { ExitWithHelp("Unexpected argument: " + _argKeyLabel); } if (!string.IsNullOrEmpty(keyId)) { ExitWithHelp("Unexpected argument: " + _argKeyId); } if (!string.IsNullOrEmpty(dataFile)) { ExitWithHelp("Unexpected argument: " + _argDataFile); } if (!string.IsNullOrEmpty(signatureFile)) { ExitWithHelp("Unexpected argument: " + _argSignatureFile); } if (!string.IsNullOrEmpty(hashAlg)) { ExitWithHelp("Unexpected argument: " + _argHashAlg); } if (!string.IsNullOrEmpty(signatureScheme)) { ExitWithHelp("Unexpected argument: " + _argSignatureScheme); } if (!string.IsNullOrEmpty(outputFormat)) { ExitWithHelp("Unexpected argument: " + _argOutputFormat); } if (!string.IsNullOrEmpty(certsDir)) { ExitWithHelp("Unexpected argument: " + _argCertsDir); } // Perform requested operation using (Pkcs11Explorer pkcs11Explorer = new Pkcs11Explorer(pkcs11Library)) { Console.WriteLine("Listing available tokens"); int j = 1; List <Token> tokens = pkcs11Explorer.GetTokens(); foreach (Token token in tokens) { Console.WriteLine(); Console.WriteLine("Token no." + j); Console.WriteLine(" Manufacturer: " + token.ManufacturerId); Console.WriteLine(" Model: " + token.Model); Console.WriteLine(" Serial number: " + token.SerialNumber); Console.WriteLine(" Label: " + token.Label); j++; } } } // Handle "--list-objects" operation mode if (listObjects == 1) { // Validate command line arguments if (string.IsNullOrEmpty(pkcs11Library)) { ExitWithHelp("Required argument: " + _argPkcs11Library); } if (string.IsNullOrEmpty(tokenSerial) && string.IsNullOrEmpty(tokenLabel)) { ExitWithHelp("Required argument: " + _argTokenSerial + " and/or " + _argTokenLabel); } if (string.IsNullOrEmpty(pin)) { ExitWithHelp("Required argument: " + _argPin); } if (!string.IsNullOrEmpty(keyLabel)) { ExitWithHelp("Unexpected argument: " + _argKeyLabel); } if (!string.IsNullOrEmpty(keyId)) { ExitWithHelp("Unexpected argument: " + _argKeyId); } if (!string.IsNullOrEmpty(dataFile)) { ExitWithHelp("Unexpected argument: " + _argDataFile); } if (!string.IsNullOrEmpty(signatureFile)) { ExitWithHelp("Unexpected argument: " + _argSignatureFile); } if (!string.IsNullOrEmpty(hashAlg)) { ExitWithHelp("Unexpected argument: " + _argHashAlg); } if (!string.IsNullOrEmpty(signatureScheme)) { ExitWithHelp("Unexpected argument: " + _argSignatureScheme); } if (!string.IsNullOrEmpty(outputFormat)) { ExitWithHelp("Unexpected argument: " + _argOutputFormat); } if (!string.IsNullOrEmpty(certsDir)) { ExitWithHelp("Unexpected argument: " + _argCertsDir); } // Perform requested operation using (Pkcs11Explorer pkcs11Explorer = new Pkcs11Explorer(pkcs11Library)) { Console.WriteLine(string.Format("Listing objects available on token with serial \"{0}\" and label \"{1}\"", tokenSerial, tokenLabel)); // Find requested token Token foundToken = null; List <Token> tokens = pkcs11Explorer.GetTokens(); foreach (Token token in tokens) { if (!string.IsNullOrEmpty(tokenLabel)) { if (0 != String.Compare(tokenLabel, token.Label, StringComparison.InvariantCultureIgnoreCase)) { continue; } } if (!string.IsNullOrEmpty(tokenSerial)) { if (0 != String.Compare(tokenSerial, token.SerialNumber, StringComparison.InvariantCultureIgnoreCase)) { continue; } } foundToken = token; break; } if (foundToken == null) { throw new TokenNotFoundException(string.Format("Token with serial \"{0}\" and label \"{1}\" was not found", tokenSerial, tokenLabel)); } // Get private keys and certificates stored in requested token List <PrivateKey> privateKeys = null; List <Certificate> certificates = null; pkcs11Explorer.GetTokenObjects(foundToken, true, pin, out privateKeys, out certificates); // Print private keys int j = 1; foreach (PrivateKey privateKey in privateKeys) { Console.WriteLine(); Console.WriteLine("Private key no." + j); Console.WriteLine(" ID (CKA_ID): " + privateKey.Id); Console.WriteLine(" Label (CKA_LABEL): " + privateKey.Label); // Print public part of RSA key if ((privateKey.PublicKey != null) && (privateKey.PublicKey is RsaKeyParameters)) { RsaKeyParameters rsa = privateKey.PublicKey as RsaKeyParameters; Console.WriteLine(" RSA exponent: " + ConvertUtils.BytesToHexString(rsa.Exponent.ToByteArrayUnsigned())); Console.WriteLine(" RSA public modulus: " + ConvertUtils.BytesToHexString(rsa.Modulus.ToByteArrayUnsigned())); } j++; } // Print certificates int k = 1; foreach (Certificate certificate in certificates) { X509Certificate2 x509Cert = CertUtils.ToDotNetObject(certificate.Data); Console.WriteLine(); Console.WriteLine("Certificate no." + k); Console.WriteLine(" ID (CKA_ID): " + certificate.Id); Console.WriteLine(" Label (CKA_LABEL): " + certificate.Label); Console.WriteLine(" Serial number: " + x509Cert.SerialNumber); Console.WriteLine(" Subject DN: " + x509Cert.Subject); Console.WriteLine(" Issuer DN: " + x509Cert.Issuer); Console.WriteLine(" Not before: " + x509Cert.NotBefore); Console.WriteLine(" Not after: " + x509Cert.NotAfter); // Print certified public RSA key if ((certificate.PublicKey != null) && (certificate.PublicKey is RsaKeyParameters)) { RsaKeyParameters rsa = certificate.PublicKey as RsaKeyParameters; Console.WriteLine(" RSA exponent: " + ConvertUtils.BytesToHexString(rsa.Exponent.ToByteArrayUnsigned())); Console.WriteLine(" RSA public modulus: " + ConvertUtils.BytesToHexString(rsa.Modulus.ToByteArrayUnsigned())); } k++; } } } // Handle "--sign" operation mode if (sign == 1) { // Use SHA256 as default hashing algorithm HashAlgorithm hashAlgorithm = HashAlgorithm.SHA256; SignatureScheme sigScheme = SignatureScheme.RSASSA_PKCS1_v1_5; OutputFormat outFormat = OutputFormat.CMS; // Validate command line arguments (_argHashAlg and _argCertsDir are optional) if (string.IsNullOrEmpty(pkcs11Library)) { ExitWithHelp("Required argument: " + _argPkcs11Library); } if (string.IsNullOrEmpty(tokenSerial) && string.IsNullOrEmpty(tokenLabel)) { ExitWithHelp("Required argument: " + _argTokenSerial + " and/or " + _argTokenLabel); } if (string.IsNullOrEmpty(pin)) { ExitWithHelp("Required argument: " + _argPin); } if (string.IsNullOrEmpty(keyLabel) && string.IsNullOrEmpty(keyId)) { ExitWithHelp("Required argument: " + _argKeyLabel + " and/or " + _argKeyId); } if (string.IsNullOrEmpty(dataFile)) { ExitWithHelp("Required argument: " + _argDataFile); } if (string.IsNullOrEmpty(signatureFile)) { ExitWithHelp("Required argument: " + _argSignatureFile); } if (!string.IsNullOrEmpty(hashAlg)) { hashAlgorithm = (HashAlgorithm)Enum.Parse(typeof(HashAlgorithm), hashAlg); } if (!string.IsNullOrEmpty(signatureScheme)) { sigScheme = (SignatureScheme)Enum.Parse(typeof(SignatureScheme), signatureScheme); } if (!string.IsNullOrEmpty(outputFormat)) { outFormat = (OutputFormat)Enum.Parse(typeof(OutputFormat), outputFormat); } // Perform requested operation using (Pkcs7SignatureGenerator pkcs7SignatureGenerator = new Pkcs7SignatureGenerator(pkcs11Library, tokenSerial, tokenLabel, pin, keyLabel, keyId, hashAlgorithm, sigScheme)) { Console.WriteLine(string.Format("Signing file \"{0}\" using private key with ID \"{1}\" and label \"{2}\" stored on token with serial \"{3}\" and label \"{4}\"", dataFile, keyId, keyLabel, tokenSerial, tokenLabel)); // Read signing certificate from the token byte[] signingCertificate = pkcs7SignatureGenerator.GetSigningCertificate(); // Read all certificates stored on the token List <byte[]> otherCertificates = pkcs7SignatureGenerator.GetAllCertificates(); // Read additional certificates from directory if (!string.IsNullOrEmpty(certsDir)) { foreach (string file in Directory.GetFiles(certsDir)) { otherCertificates.Add(File.ReadAllBytes(file)); } } // Build certification path for the signing certificate ICollection <Org.BouncyCastle.X509.X509Certificate> certPath = CertUtils.BuildCertPath(signingCertificate, otherCertificates, true); // Perform signing and signature encoding if (outFormat == OutputFormat.CMS) { // Read data that should be signed byte[] dataFileContent = File.ReadAllBytes(dataFile); // Generate detached PKCS#7 signature byte[] signature = pkcs7SignatureGenerator.GenerateSignature(dataFileContent, true, CertUtils.ToBouncyCastleObject(signingCertificate), certPath); // Save signature to the file File.WriteAllBytes(signatureFile, signature); } else if (outFormat == OutputFormat.SMIME) { MemoryStream dataStream = null; MemoryStream signatureStream = null; try { // Construct MIME part for data TextPart dataPart = new TextPart("plain"); dataPart.Text = File.ReadAllText(dataFile, Encoding.UTF8); // Read data that should be signed dataStream = new MemoryStream(); dataPart.WriteTo(dataStream); // Generate detached PKCS#7 signature byte[] signature = pkcs7SignatureGenerator.GenerateSignature(dataStream.ToArray(), true, CertUtils.ToBouncyCastleObject(signingCertificate), certPath); signatureStream = new MemoryStream(signature); // Construct MIME part for signature MimePart signaturePart = new MimePart("application", "x-pkcs7-signature"); signaturePart.Content = new MimeContent(signatureStream, ContentEncoding.Binary); signaturePart.ContentDisposition = new ContentDisposition(ContentDisposition.Attachment); signaturePart.ContentTransferEncoding = ContentEncoding.Base64; signaturePart.FileName = Path.GetFileName("smime.p7s"); // Construct multipart MIME message var multipart = new Multipart("signed"); multipart.ContentType.Parameters["micalg"] = HashAlgorithmUtils.GetHashMicalgName(hashAlgorithm); multipart.ContentType.Parameters["protocol"] = "application/x-pkcs7-signature"; multipart.Add(dataPart); multipart.Add(signaturePart); // Save signature to the file multipart.WriteTo(signatureFile); } finally { if (dataStream != null) { dataStream.Dispose(); dataStream = null; } if (signatureStream != null) { signatureStream.Dispose(); signatureStream = null; } } } else { throw new NotSupportedException(string.Format("Output format \"{0}\" is not supported", outputFormat)); } } } } catch (Exception ex) { Console.WriteLine(@"Operation error: " + ex.GetType() + " - " + ex.Message); Console.WriteLine(ex.StackTrace); Environment.Exit(_exitError); } Environment.Exit(_exitSuccess); }