/// <summary> /// Generates certificate request in PKCS#10 format defined by RFC 2986 /// </summary> /// <param name="session">Session with user logged in</param> /// <param name="publicKeyHandle">Handle of public key that should be contained in generated request</param> /// <param name="privateKeyHandle">Handle of private key that should be used for the creation of request signature</param> /// <param name="subjectDistinguishedName">Subject entity's distinguished name</param> /// <param name="hashAlgorithm">Hash algorihtm used for the creation of request signature</param> /// <returns>Certificate request in PKCS#10 format</returns> public static byte[] GeneratePkcs10(Session session, ObjectHandle publicKeyHandle, ObjectHandle privateKeyHandle, string subjectDistinguishedName, HashAlgorithm hashAlgorithm) { List<CKA> pubKeyAttrsToRead = new List<CKA>(); pubKeyAttrsToRead.Add(CKA.CKA_KEY_TYPE); pubKeyAttrsToRead.Add(CKA.CKA_MODULUS); pubKeyAttrsToRead.Add(CKA.CKA_PUBLIC_EXPONENT); // Read public key attributes List<ObjectAttribute> publicKeyAttributes = session.GetAttributeValue(publicKeyHandle, pubKeyAttrsToRead); if (CKK.CKK_RSA != (CKK)publicKeyAttributes[0].GetValueAsUlong()) throw new NotSupportedException("Currently only RSA keys are supported"); // Create instance of RsaKeyParameters class usable for BouncyCastle BigInteger modulus = new BigInteger(1, publicKeyAttributes[1].GetValueAsByteArray()); BigInteger publicExponent = new BigInteger(1, publicKeyAttributes[2].GetValueAsByteArray()); RsaKeyParameters publicKeyParameters = new RsaKeyParameters(false, modulus, publicExponent); // Determine algorithms Mechanism mechanism = null; string signatureAlgorihtm = null; switch (hashAlgorithm) { case HashAlgorithm.SHA1: mechanism = new Mechanism(CKM.CKM_SHA1_RSA_PKCS); signatureAlgorihtm = PkcsObjectIdentifiers.Sha1WithRsaEncryption.Id; break; case HashAlgorithm.SHA256: mechanism = new Mechanism(CKM.CKM_SHA256_RSA_PKCS); signatureAlgorihtm = PkcsObjectIdentifiers.Sha256WithRsaEncryption.Id; break; case HashAlgorithm.SHA384: mechanism = new Mechanism(CKM.CKM_SHA384_RSA_PKCS); signatureAlgorihtm = PkcsObjectIdentifiers.Sha384WithRsaEncryption.Id; break; case HashAlgorithm.SHA512: mechanism = new Mechanism(CKM.CKM_SHA512_RSA_PKCS); signatureAlgorihtm = PkcsObjectIdentifiers.Sha512WithRsaEncryption.Id; break; } // Generate and sign PKCS#10 request Pkcs10CertificationRequestDelaySigned pkcs10 = new Pkcs10CertificationRequestDelaySigned(signatureAlgorihtm, new X509Name(subjectDistinguishedName), publicKeyParameters, null); byte[] signature = session.Sign(mechanism, privateKeyHandle, pkcs10.GetDataToSign()); pkcs10.SignRequest(new DerBitString(signature)); return pkcs10.GetDerEncoded(); }
/// <summary> /// Generates asymetric key pair /// </summary> /// <param name='session'>Read-write session with user logged in</param> /// <param name='ckaLabel'>Value of CKA_LABEL attribute for generated keys</param> /// <param name='ckaId'>Value of CKA_ID attribute for generated keys</param> /// <param name='publicKeyHandle'>Output parameter for public key object handle</param> /// <param name='privateKeyHandle'>Output parameter for private key object handle</param> public static void GenerateKeyPair(Session session, string ckaLabel, byte[] ckaId, out ObjectHandle publicKeyHandle, out ObjectHandle privateKeyHandle) { // Prepare attribute template of new public key List<ObjectAttribute> publicKeyAttributes = new List<ObjectAttribute>(); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_TOKEN, true)); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PRIVATE, false)); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, ckaLabel)); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ID, ckaId)); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ENCRYPT, true)); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_VERIFY, true)); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_VERIFY_RECOVER, true)); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_WRAP, true)); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_MODULUS_BITS, 1024)); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PUBLIC_EXPONENT, new byte[] { 0x01, 0x00, 0x01 })); // Prepare attribute template of new private key List<ObjectAttribute> privateKeyAttributes = new List<ObjectAttribute>(); privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_TOKEN, true)); privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PRIVATE, true)); privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, ckaLabel)); privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ID, ckaId)); privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_SENSITIVE, true)); privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_DECRYPT, true)); privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_SIGN, true)); privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_SIGN_RECOVER, true)); privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_UNWRAP, true)); // Specify key generation mechanism Mechanism mechanism = new Mechanism(CKM.CKM_RSA_PKCS_KEY_PAIR_GEN); // Generate key pair session.GenerateKeyPair(mechanism, publicKeyAttributes, privateKeyAttributes, out publicKeyHandle, out privateKeyHandle); }
/// <summary> /// Decrypts data and verifies a signature of data /// </summary> /// <param name="verificationMechanism">Verification mechanism</param> /// <param name="verificationKeyHandle">Handle of the verification key</param> /// <param name="decryptionMechanism">Decryption mechanism</param> /// <param name="decryptionKeyHandle">Handle of the decryption key</param> /// <param name="inputStream">Input stream from which data to be processed should be read</param> /// <param name="outputStream">Output stream where decrypted data should be written</param> /// <param name="signature">Signature</param> /// <param name="isValid">Flag indicating whether signature is valid</param> /// <param name="bufferLength">Size of read buffer in bytes</param> public void DecryptVerify(Mechanism verificationMechanism, ObjectHandle verificationKeyHandle, Mechanism decryptionMechanism, ObjectHandle decryptionKeyHandle, Stream inputStream, Stream outputStream, byte[] signature, out bool isValid, int bufferLength) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (verificationMechanism == null) throw new ArgumentNullException("verificationMechanism"); if (verificationKeyHandle == null) throw new ArgumentNullException("verificationKeyHandle"); if (decryptionMechanism == null) throw new ArgumentNullException("decryptionMechanism"); if (decryptionKeyHandle == null) throw new ArgumentNullException("decryptionKeyHandle"); if (inputStream == null) throw new ArgumentNullException("inputStream"); if (outputStream == null) throw new ArgumentNullException("outputStream"); if (signature == null) throw new ArgumentNullException("signature"); if (bufferLength < 1) throw new ArgumentException("Value has to be positive number", "bufferLength"); if (Platform.UnmanagedLongSize == 4) { if (Platform.StructPackingSize == 0) _session40.DecryptVerify(verificationMechanism.Mechanism40, verificationKeyHandle.ObjectHandle40, decryptionMechanism.Mechanism40, decryptionKeyHandle.ObjectHandle40, inputStream, outputStream, signature, out isValid, bufferLength); else _session41.DecryptVerify(verificationMechanism.Mechanism41, verificationKeyHandle.ObjectHandle41, decryptionMechanism.Mechanism41, decryptionKeyHandle.ObjectHandle41, inputStream, outputStream, signature, out isValid, bufferLength); } else { if (Platform.StructPackingSize == 0) _session80.DecryptVerify(verificationMechanism.Mechanism80, verificationKeyHandle.ObjectHandle80, decryptionMechanism.Mechanism80, decryptionKeyHandle.ObjectHandle80, inputStream, outputStream, signature, out isValid, bufferLength); else _session81.DecryptVerify(verificationMechanism.Mechanism81, verificationKeyHandle.ObjectHandle81, decryptionMechanism.Mechanism81, decryptionKeyHandle.ObjectHandle81, inputStream, outputStream, signature, out isValid, bufferLength); } }
/// <summary> /// Disposes object /// </summary> /// <param name="disposing">Flag indicating whether managed resources should be disposed</param> protected virtual void Dispose(bool disposing) { if (!this._disposed) { // Dispose managed objects if (disposing) { _allCertificates = null; _signingCertificate = null; _hashAlgorihtm = HashAlgorithm.SHA512; _ckaId = null; _ckaLabel = null; _privateKeyHandle = null; if (_session != null) { try { _session.Logout(); } catch { // Any exceptions can be safely ignored here } _session.Dispose(); _session = null; } _slot = null; if (_pkcs11 != null) { _pkcs11.Dispose(); _pkcs11 = null; } } // Dispose unmanaged objects _disposed = true; } }
/// <summary> /// Encrypts multi-part data /// </summary> /// <param name="mechanism">Encryption mechanism</param> /// <param name="keyHandle">Handle of the encryption key</param> /// <param name="inputStream">Input stream from which data to be encrypted should be read</param> /// <param name="outputStream">Output stream where encrypted data should be written</param> /// <param name="bufferLength">Size of read buffer in bytes</param> public void Encrypt(Mechanism mechanism, ObjectHandle keyHandle, Stream inputStream, Stream outputStream, int bufferLength) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (mechanism == null) throw new ArgumentNullException("mechanism"); if (keyHandle == null) throw new ArgumentNullException("keyHandle"); if (inputStream == null) throw new ArgumentNullException("inputStream"); if (outputStream == null) throw new ArgumentNullException("outputStream"); if (bufferLength < 1) throw new ArgumentException("Value has to be positive number", "bufferLength"); if (Platform.UnmanagedLongSize == 4) { if (Platform.StructPackingSize == 0) _session40.Encrypt(mechanism.Mechanism40, keyHandle.ObjectHandle40, inputStream, outputStream, bufferLength); else _session41.Encrypt(mechanism.Mechanism41, keyHandle.ObjectHandle41, inputStream, outputStream, bufferLength); } else { if (Platform.StructPackingSize == 0) _session80.Encrypt(mechanism.Mechanism80, keyHandle.ObjectHandle80, inputStream, outputStream, bufferLength); else _session81.Encrypt(mechanism.Mechanism81, keyHandle.ObjectHandle81, inputStream, outputStream, bufferLength); } }
/// <summary> /// Modifies the value of one or more attributes of an object /// </summary> /// <param name="objectHandle">Handle of object whose attributes should be modified</param> /// <param name="attributes">List of attributes that should be modified</param> public void SetAttributeValue(ObjectHandle objectHandle, List<ObjectAttribute> attributes) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (objectHandle == null) throw new ArgumentNullException("objectHandle"); if (attributes == null) throw new ArgumentNullException("attributes"); if (attributes.Count < 1) throw new ArgumentException("No attributes specified", "attributes"); if (Platform.UnmanagedLongSize == 4) { if (Platform.StructPackingSize == 0) { List<HighLevelAPI40.ObjectAttribute> hlaAttributes = ObjectAttribute.ConvertToHighLevelAPI40List(attributes); _session40.SetAttributeValue(objectHandle.ObjectHandle40, hlaAttributes); } else { List<HighLevelAPI41.ObjectAttribute> hlaAttributes = ObjectAttribute.ConvertToHighLevelAPI41List(attributes); _session41.SetAttributeValue(objectHandle.ObjectHandle41, hlaAttributes); } } else { if (Platform.StructPackingSize == 0) { List<HighLevelAPI80.ObjectAttribute> hlaAttributes = ObjectAttribute.ConvertToHighLevelAPI80List(attributes); _session80.SetAttributeValue(objectHandle.ObjectHandle80, hlaAttributes); } else { List<HighLevelAPI81.ObjectAttribute> hlaAttributes = ObjectAttribute.ConvertToHighLevelAPI81List(attributes); _session81.SetAttributeValue(objectHandle.ObjectHandle81, hlaAttributes); } } }
/// <summary> /// Obtains the value of one or more attributes of an object /// </summary> /// <param name="objectHandle">Handle of object whose attributes should be read</param> /// <param name="attributes">List of attributes that should be read</param> /// <returns>Object attributes</returns> public List<ObjectAttribute> GetAttributeValue(ObjectHandle objectHandle, List<CKA> attributes) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (objectHandle == null) throw new ArgumentNullException("objectHandle"); if (attributes == null) throw new ArgumentNullException("attributes"); if (attributes.Count < 1) throw new ArgumentException("No attributes specified", "attributes"); List<ulong> ulongAttributes = new List<ulong>(); foreach (CKA attribute in attributes) ulongAttributes.Add(Convert.ToUInt64((uint)attribute)); return GetAttributeValue(objectHandle, ulongAttributes); }
/// <summary> /// Copies an object, creating a new object for the copy /// </summary> /// <param name="objectHandle">Handle of object to be copied</param> /// <param name="attributes">New values for any attributes of the object that can ordinarily be modified</param> /// <returns>Handle of copied object</returns> public ObjectHandle CopyObject(ObjectHandle objectHandle, List<ObjectAttribute> attributes) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (objectHandle == null) throw new ArgumentNullException("objectHandle"); if (Platform.UnmanagedLongSize == 4) { if (Platform.StructPackingSize == 0) { List<HighLevelAPI40.ObjectAttribute> hlaAttributes = ObjectAttribute.ConvertToHighLevelAPI40List(attributes); HighLevelAPI40.ObjectHandle hlaObjectHandle = _session40.CopyObject(objectHandle.ObjectHandle40, hlaAttributes); return new ObjectHandle(hlaObjectHandle); } else { List<HighLevelAPI41.ObjectAttribute> hlaAttributes = ObjectAttribute.ConvertToHighLevelAPI41List(attributes); HighLevelAPI41.ObjectHandle hlaObjectHandle = _session41.CopyObject(objectHandle.ObjectHandle41, hlaAttributes); return new ObjectHandle(hlaObjectHandle); } } else { if (Platform.StructPackingSize == 0) { List<HighLevelAPI80.ObjectAttribute> hlaAttributes = ObjectAttribute.ConvertToHighLevelAPI80List(attributes); HighLevelAPI80.ObjectHandle hlaObjectHandle = _session80.CopyObject(objectHandle.ObjectHandle80, hlaAttributes); return new ObjectHandle(hlaObjectHandle); } else { List<HighLevelAPI81.ObjectAttribute> hlaAttributes = ObjectAttribute.ConvertToHighLevelAPI81List(attributes); HighLevelAPI81.ObjectHandle hlaObjectHandle = _session81.CopyObject(objectHandle.ObjectHandle81, hlaAttributes); return new ObjectHandle(hlaObjectHandle); } } }
/// <summary> /// Derives a key from a base key, creating a new key object /// </summary> /// <param name="mechanism">Derivation mechanism</param> /// <param name="baseKeyHandle">Handle of base key</param> /// <param name="attributes">Attributes for the new key</param> /// <returns>Handle of derived key</returns> public ObjectHandle DeriveKey(Mechanism mechanism, ObjectHandle baseKeyHandle, List<ObjectAttribute> attributes) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (mechanism == null) throw new ArgumentNullException("mechanism"); if (baseKeyHandle == null) throw new ArgumentNullException("baseKeyHandle"); if (Platform.UnmanagedLongSize == 4) { if (Platform.StructPackingSize == 0) { List<HighLevelAPI40.ObjectAttribute> hlaAttributes = ObjectAttribute.ConvertToHighLevelAPI40List(attributes); HighLevelAPI40.ObjectHandle unwrappedKeyHandle = _session40.DeriveKey(mechanism.Mechanism40, baseKeyHandle.ObjectHandle40, hlaAttributes); return new ObjectHandle(unwrappedKeyHandle); } else { List<HighLevelAPI41.ObjectAttribute> hlaAttributes = ObjectAttribute.ConvertToHighLevelAPI41List(attributes); HighLevelAPI41.ObjectHandle unwrappedKeyHandle = _session41.DeriveKey(mechanism.Mechanism41, baseKeyHandle.ObjectHandle41, hlaAttributes); return new ObjectHandle(unwrappedKeyHandle); } } else { if (Platform.StructPackingSize == 0) { List<HighLevelAPI80.ObjectAttribute> hlaAttributes = ObjectAttribute.ConvertToHighLevelAPI80List(attributes); HighLevelAPI80.ObjectHandle unwrappedKeyHandle = _session80.DeriveKey(mechanism.Mechanism80, baseKeyHandle.ObjectHandle80, hlaAttributes); return new ObjectHandle(unwrappedKeyHandle); } else { List<HighLevelAPI81.ObjectAttribute> hlaAttributes = ObjectAttribute.ConvertToHighLevelAPI81List(attributes); HighLevelAPI81.ObjectHandle unwrappedKeyHandle = _session81.DeriveKey(mechanism.Mechanism81, baseKeyHandle.ObjectHandle81, hlaAttributes); return new ObjectHandle(unwrappedKeyHandle); } } }
/// <summary> /// Digests and decrypts data /// </summary> /// <param name="digestingMechanism">Digesting mechanism</param> /// <param name="decryptionMechanism">Decryption mechanism</param> /// <param name="keyHandle">Handle of the decryption key</param> /// <param name="data">Data to be processed</param> /// <param name="digest">Digest</param> /// <param name="decryptedData">Decrypted data</param> public void DecryptDigest(Mechanism digestingMechanism, Mechanism decryptionMechanism, ObjectHandle keyHandle, byte[] data, out byte[] digest, out byte[] decryptedData) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (digestingMechanism == null) throw new ArgumentNullException("digestingMechanism"); if (decryptionMechanism == null) throw new ArgumentNullException("decryptionMechanism"); if (keyHandle == null) throw new ArgumentNullException("keyHandle"); if (data == null) throw new ArgumentNullException("data"); using (MemoryStream inputMemoryStream = new MemoryStream(data), outputMemorySteam = new MemoryStream()) { digest = DecryptDigest(digestingMechanism, decryptionMechanism, keyHandle, inputMemoryStream, outputMemorySteam); decryptedData = outputMemorySteam.ToArray(); } }
/// <summary> /// Verifies signature of data, where the data can be recovered from the signature /// </summary> /// <param name="mechanism">Verification mechanism;</param> /// <param name="keyHandle">Verification key</param> /// <param name="signature">Signature</param> /// <param name="isValid">Flag indicating whether signature is valid</param> /// <returns>Data recovered from the signature</returns> public byte[] VerifyRecover(Mechanism mechanism, ObjectHandle keyHandle, byte[] signature, out bool isValid) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (mechanism == null) throw new ArgumentNullException("mechanism"); if (keyHandle == null) throw new ArgumentNullException("keyHandle"); if (signature == null) throw new ArgumentNullException("signature"); if (Platform.UnmanagedLongSize == 4) { if (Platform.StructPackingSize == 0) return _session40.VerifyRecover(mechanism.Mechanism40, keyHandle.ObjectHandle40, signature, out isValid); else return _session41.VerifyRecover(mechanism.Mechanism41, keyHandle.ObjectHandle41, signature, out isValid); } else { if (Platform.StructPackingSize == 0) return _session80.VerifyRecover(mechanism.Mechanism80, keyHandle.ObjectHandle80, signature, out isValid); else return _session81.VerifyRecover(mechanism.Mechanism81, keyHandle.ObjectHandle81, signature, out isValid); } }
/// <summary> /// Verifies a signature of data, where the signature is an appendix to the data /// </summary> /// <param name="mechanism">Verification mechanism;</param> /// <param name="keyHandle">Verification key</param> /// <param name="inputStream">Input stream from which data that was signed should be read</param> /// <param name="signature">Signature</param> /// <param name="isValid">Flag indicating whether signature is valid</param> public void Verify(Mechanism mechanism, ObjectHandle keyHandle, Stream inputStream, byte[] signature, out bool isValid) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (mechanism == null) throw new ArgumentNullException("mechanism"); if (keyHandle == null) throw new ArgumentNullException("keyHandle"); if (inputStream == null) throw new ArgumentNullException("inputStream"); if (signature == null) throw new ArgumentNullException("signature"); Verify(mechanism, keyHandle, inputStream, signature, out isValid, 4096); }
/// <summary> /// Signs multi-part data, where the signature is an appendix to the data /// </summary> /// <param name="mechanism">Signature mechanism</param> /// <param name="keyHandle">Signature key</param> /// <param name="inputStream">Input stream from which data should be read</param> /// <returns>Signature</returns> public byte[] Sign(Mechanism mechanism, ObjectHandle keyHandle, Stream inputStream) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (mechanism == null) throw new ArgumentNullException("mechanism"); if (keyHandle == null) throw new ArgumentNullException("keyHandle"); if (inputStream == null) throw new ArgumentNullException("inputStream"); return Sign(mechanism, keyHandle, inputStream, 4096); }
/// <summary> /// Generates asymetric key pair. /// </summary> /// <param name='session'>Read-write session with user logged in</param> /// <param name='publicKeyHandle'>Output parameter for public key object handle</param> /// <param name='privateKeyHandle'>Output parameter for private key object handle</param> public static void GenerateKeyPair(Session session, out ObjectHandle publicKeyHandle, out ObjectHandle privateKeyHandle) { // The CKA_ID attribute is intended as a means of distinguishing multiple key pairs held by the same subject byte[] ckaId = session.GenerateRandom(20); // Prepare attribute template of new public key List<ObjectAttribute> publicKeyAttributes = new List<ObjectAttribute>(); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_TOKEN, true)); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PRIVATE, false)); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, Settings.ApplicationName)); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ID, ckaId)); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ENCRYPT, true)); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_VERIFY, true)); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_VERIFY_RECOVER, true)); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_WRAP, true)); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_MODULUS_BITS, 1024)); publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PUBLIC_EXPONENT, new byte[] { 0x01, 0x00, 0x01 })); // Prepare attribute template of new private key List<ObjectAttribute> privateKeyAttributes = new List<ObjectAttribute>(); privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_TOKEN, true)); privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PRIVATE, true)); privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, Settings.ApplicationName)); privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ID, ckaId)); privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_SENSITIVE, true)); privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_DECRYPT, true)); privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_SIGN, true)); privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_SIGN_RECOVER, true)); privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_UNWRAP, true)); // Specify key generation mechanism Mechanism mechanism = new Mechanism(CKM.CKM_RSA_PKCS_KEY_PAIR_GEN); // Generate key pair session.GenerateKeyPair(mechanism, publicKeyAttributes, privateKeyAttributes, out publicKeyHandle, out privateKeyHandle); }
/// <summary> /// Initializes a new instance of the Pkcs11Signature class /// </summary> /// <param name="libraryPath">Path to the unmanaged PCKS#11 library</param> /// <param name="tokenSerial">Serial number of the token (smartcard) that contains signing key. May be null if tokenLabel is specified.</param> /// <param name="tokenLabel">Label of of the token (smartcard) that contains signing key. May be null if tokenSerial is specified.</param> /// <param name="pin">PIN for the token (smartcard)</param> /// <param name="ckaLabel">Label (value of CKA_LABEL attribute) of the private key used for signing. May be null if ckaId is specified.</param> /// <param name="ckaId">Identifier (value of CKA_ID attribute) of the private key used for signing. May be null if ckaLabel is specified.</param> /// <param name="hashAlgorihtm">Hash algorihtm used for the signature creation</param> private void InitializePkcs7RsaSignature(string libraryPath, string tokenSerial, string tokenLabel, byte[] pin, string ckaLabel, byte[] ckaId, HashAlgorithm hashAlgorihtm) { try { if (string.IsNullOrEmpty(libraryPath)) throw new ArgumentNullException("libraryPath"); _pkcs11 = new Pkcs11(libraryPath, true); _slot = FindSlot(tokenSerial, tokenLabel); if (_slot == null) throw new TokenNotFoundException(string.Format("Token with serial \"{0}\" and label \"{1}\" was not found", tokenSerial, tokenLabel)); _session = _slot.OpenSession(true); _session.Login(CKU.CKU_USER, pin); _privateKeyHandle = FindPrivateKey(ckaLabel, ckaId); _ckaLabel = ckaLabel; _ckaId = ckaId; if (!Enum.IsDefined(typeof(HashAlgorithm), hashAlgorihtm)) throw new ArgumentException("Invalid hash algorithm specified"); _hashAlgorihtm = hashAlgorihtm; } catch { if (_session != null) { _session.Dispose(); _session = null; } if (_pkcs11 != null) { _pkcs11.Dispose(); _pkcs11 = null; } throw; } }
/// <summary> /// Generates a public/private key pair, creating new key objects /// </summary> /// <param name="mechanism">Key generation mechanism</param> /// <param name="publicKeyAttributes">Attributes of the public key</param> /// <param name="privateKeyAttributes">Attributes of the private key</param> /// <param name="publicKeyHandle">Handle of the new public key</param> /// <param name="privateKeyHandle">Handle of the new private key</param> public void GenerateKeyPair(Mechanism mechanism, List<ObjectAttribute> publicKeyAttributes, List<ObjectAttribute> privateKeyAttributes, out ObjectHandle publicKeyHandle, out ObjectHandle privateKeyHandle) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (mechanism == null) throw new ArgumentNullException("mechanism"); if (Platform.UnmanagedLongSize == 4) { if (Platform.StructPackingSize == 0) { List<HighLevelAPI40.ObjectAttribute> hlaPublicKeyAttributes = ObjectAttribute.ConvertToHighLevelAPI40List(publicKeyAttributes); List<HighLevelAPI40.ObjectAttribute> hlaPrivateKeyAttributes = ObjectAttribute.ConvertToHighLevelAPI40List(privateKeyAttributes); HighLevelAPI40.ObjectHandle hlaPublicKeyHandle = null; HighLevelAPI40.ObjectHandle hlaPrivateKeyHandle = null; _session40.GenerateKeyPair(mechanism.Mechanism40, hlaPublicKeyAttributes, hlaPrivateKeyAttributes, out hlaPublicKeyHandle, out hlaPrivateKeyHandle); publicKeyHandle = new ObjectHandle(hlaPublicKeyHandle); privateKeyHandle = new ObjectHandle(hlaPrivateKeyHandle); } else { List<HighLevelAPI41.ObjectAttribute> hlaPublicKeyAttributes = ObjectAttribute.ConvertToHighLevelAPI41List(publicKeyAttributes); List<HighLevelAPI41.ObjectAttribute> hlaPrivateKeyAttributes = ObjectAttribute.ConvertToHighLevelAPI41List(privateKeyAttributes); HighLevelAPI41.ObjectHandle hlaPublicKeyHandle = null; HighLevelAPI41.ObjectHandle hlaPrivateKeyHandle = null; _session41.GenerateKeyPair(mechanism.Mechanism41, hlaPublicKeyAttributes, hlaPrivateKeyAttributes, out hlaPublicKeyHandle, out hlaPrivateKeyHandle); publicKeyHandle = new ObjectHandle(hlaPublicKeyHandle); privateKeyHandle = new ObjectHandle(hlaPrivateKeyHandle); } } else { if (Platform.StructPackingSize == 0) { List<HighLevelAPI80.ObjectAttribute> hlaPublicKeyAttributes = ObjectAttribute.ConvertToHighLevelAPI80List(publicKeyAttributes); List<HighLevelAPI80.ObjectAttribute> hlaPrivateKeyAttributes = ObjectAttribute.ConvertToHighLevelAPI80List(privateKeyAttributes); HighLevelAPI80.ObjectHandle hlaPublicKeyHandle = null; HighLevelAPI80.ObjectHandle hlaPrivateKeyHandle = null; _session80.GenerateKeyPair(mechanism.Mechanism80, hlaPublicKeyAttributes, hlaPrivateKeyAttributes, out hlaPublicKeyHandle, out hlaPrivateKeyHandle); publicKeyHandle = new ObjectHandle(hlaPublicKeyHandle); privateKeyHandle = new ObjectHandle(hlaPrivateKeyHandle); } else { List<HighLevelAPI81.ObjectAttribute> hlaPublicKeyAttributes = ObjectAttribute.ConvertToHighLevelAPI81List(publicKeyAttributes); List<HighLevelAPI81.ObjectAttribute> hlaPrivateKeyAttributes = ObjectAttribute.ConvertToHighLevelAPI81List(privateKeyAttributes); HighLevelAPI81.ObjectHandle hlaPublicKeyHandle = null; HighLevelAPI81.ObjectHandle hlaPrivateKeyHandle = null; _session81.GenerateKeyPair(mechanism.Mechanism81, hlaPublicKeyAttributes, hlaPrivateKeyAttributes, out hlaPublicKeyHandle, out hlaPrivateKeyHandle); publicKeyHandle = new ObjectHandle(hlaPublicKeyHandle); privateKeyHandle = new ObjectHandle(hlaPrivateKeyHandle); } } }
/// <summary> /// Wraps (i.e., encrypts) a private or secret key /// </summary> /// <param name="mechanism">Wrapping mechanism</param> /// <param name="wrappingKeyHandle">Handle of wrapping key</param> /// <param name="keyHandle">Handle of key to be wrapped</param> /// <returns>Wrapped key</returns> public byte[] WrapKey(Mechanism mechanism, ObjectHandle wrappingKeyHandle, ObjectHandle keyHandle) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (mechanism == null) throw new ArgumentNullException("mechanism"); if (wrappingKeyHandle == null) throw new ArgumentNullException("wrappingKeyHandle"); if (keyHandle == null) throw new ArgumentNullException("keyHandle"); if (Platform.UnmanagedLongSize == 4) { if (Platform.StructPackingSize == 0) return _session40.WrapKey(mechanism.Mechanism40, wrappingKeyHandle.ObjectHandle40, keyHandle.ObjectHandle40); else return _session41.WrapKey(mechanism.Mechanism41, wrappingKeyHandle.ObjectHandle41, keyHandle.ObjectHandle41); } else { if (Platform.StructPackingSize == 0) return _session80.WrapKey(mechanism.Mechanism80, wrappingKeyHandle.ObjectHandle80, keyHandle.ObjectHandle80); else return _session81.WrapKey(mechanism.Mechanism81, wrappingKeyHandle.ObjectHandle81, keyHandle.ObjectHandle81); } }
/// <summary> /// Digests and decrypts data /// </summary> /// <param name="digestingMechanism">Digesting mechanism</param> /// <param name="decryptionMechanism">Decryption mechanism</param> /// <param name="keyHandle">Handle of the decryption key</param> /// <param name="inputStream">Input stream from which data to be processed should be read</param> /// <param name="outputStream">Output stream where decrypted data should be written</param> /// <returns>Digest</returns> public byte[] DecryptDigest(Mechanism digestingMechanism, Mechanism decryptionMechanism, ObjectHandle keyHandle, Stream inputStream, Stream outputStream) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (digestingMechanism == null) throw new ArgumentNullException("digestingMechanism"); if (decryptionMechanism == null) throw new ArgumentNullException("decryptionMechanism"); if (keyHandle == null) throw new ArgumentNullException("keyHandle"); if (inputStream == null) throw new ArgumentNullException("inputStream"); if (outputStream == null) throw new ArgumentNullException("outputStream"); return DecryptDigest(digestingMechanism, decryptionMechanism, keyHandle, inputStream, outputStream, 4096); }
/// <summary> /// Restores the cryptographic operations state of a session from an array of bytes obtained with GetOperationState /// </summary> /// <param name="state">Array of bytes obtained with GetOperationState</param> /// <param name="encryptionKey">CK_INVALID_HANDLE or handle to the key which will be used for an ongoing encryption or decryption operation in the restored session</param> /// <param name="authenticationKey">CK_INVALID_HANDLE or handle to the key which will be used for an ongoing signature, MACing, or verification operation in the restored session</param> public void SetOperationState(byte[] state, ObjectHandle encryptionKey, ObjectHandle authenticationKey) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (state == null) throw new ArgumentNullException("state"); if (encryptionKey == null) throw new ArgumentNullException("encryptionKey"); if (authenticationKey == null) throw new ArgumentNullException("authenticationKey"); if (Platform.UnmanagedLongSize == 4) { if (Platform.StructPackingSize == 0) _session40.SetOperationState(state, encryptionKey.ObjectHandle40, authenticationKey.ObjectHandle40); else _session41.SetOperationState(state, encryptionKey.ObjectHandle41, authenticationKey.ObjectHandle41); } else { if (Platform.StructPackingSize == 0) _session80.SetOperationState(state, encryptionKey.ObjectHandle80, authenticationKey.ObjectHandle80); else _session81.SetOperationState(state, encryptionKey.ObjectHandle81, authenticationKey.ObjectHandle81); } }
/// <summary> /// Signs and encrypts data /// </summary> /// <param name="signingMechanism">Signing mechanism</param> /// <param name="signingKeyHandle">Handle of the signing key</param> /// <param name="encryptionMechanism">Encryption mechanism</param> /// <param name="encryptionKeyHandle">Handle of the encryption key</param> /// <param name="data">Data to be processed</param> /// <param name="signature">Signature</param> /// <param name="encryptedData">Encrypted data</param> public void SignEncrypt(Mechanism signingMechanism, ObjectHandle signingKeyHandle, Mechanism encryptionMechanism, ObjectHandle encryptionKeyHandle, byte[] data, out byte[] signature, out byte[] encryptedData) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (signingMechanism == null) throw new ArgumentNullException("signingMechanism"); if (signingKeyHandle == null) throw new ArgumentNullException("signingKeyHandle"); if (encryptionMechanism == null) throw new ArgumentNullException("encryptionMechanism"); if (encryptionKeyHandle == null) throw new ArgumentNullException("encryptionKeyHandle"); if (data == null) throw new ArgumentNullException("data"); using (MemoryStream inputMemoryStream = new MemoryStream(data), outputMemorySteam = new MemoryStream()) { signature = SignEncrypt(signingMechanism, signingKeyHandle, encryptionMechanism, encryptionKeyHandle, inputMemoryStream, outputMemorySteam); encryptedData = outputMemorySteam.ToArray(); } }
/// <summary> /// Gets the size of an object in bytes. /// </summary> /// <param name="objectHandle">Handle of object</param> /// <returns>Size of an object in bytes</returns> public ulong GetObjectSize(ObjectHandle objectHandle) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (objectHandle == null) throw new ArgumentNullException("objectHandle"); if (Platform.UnmanagedLongSize == 4) { if (Platform.StructPackingSize == 0) return _session40.GetObjectSize(objectHandle.ObjectHandle40); else return _session41.GetObjectSize(objectHandle.ObjectHandle41); } else { if (Platform.StructPackingSize == 0) return _session80.GetObjectSize(objectHandle.ObjectHandle80); else return _session81.GetObjectSize(objectHandle.ObjectHandle81); } }
/// <summary> /// Signs and encrypts data /// </summary> /// <param name="signingMechanism">Signing mechanism</param> /// <param name="signingKeyHandle">Handle of the signing key</param> /// <param name="encryptionMechanism">Encryption mechanism</param> /// <param name="encryptionKeyHandle">Handle of the encryption key</param> /// <param name="inputStream">Input stream from which data to be processed should be read</param> /// <param name="outputStream">Output stream where encrypted data should be written</param> /// <returns>Signature</returns> public byte[] SignEncrypt(Mechanism signingMechanism, ObjectHandle signingKeyHandle, Mechanism encryptionMechanism, ObjectHandle encryptionKeyHandle, Stream inputStream, Stream outputStream) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (signingMechanism == null) throw new ArgumentNullException("signingMechanism"); if (signingKeyHandle == null) throw new ArgumentNullException("signingKeyHandle"); if (encryptionMechanism == null) throw new ArgumentNullException("encryptionMechanism"); if (encryptionKeyHandle == null) throw new ArgumentNullException("encryptionKeyHandle"); if (inputStream == null) throw new ArgumentNullException("inputStream"); if (outputStream == null) throw new ArgumentNullException("outputStream"); return SignEncrypt(signingMechanism, signingKeyHandle, encryptionMechanism, encryptionKeyHandle, inputStream, outputStream, 4096); }
/// <summary> /// Obtains the value of one or more attributes of an object /// </summary> /// <param name="objectHandle">Handle of object whose attributes should be read</param> /// <param name="attributes">List of attributes that should be read</param> /// <returns>Object attributes</returns> public List<ObjectAttribute> GetAttributeValue(ObjectHandle objectHandle, List<ulong> attributes) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (objectHandle == null) throw new ArgumentNullException("objectHandle"); if (attributes == null) throw new ArgumentNullException("attributes"); if (attributes.Count < 1) throw new ArgumentException("No attributes specified", "attributes"); if (Platform.UnmanagedLongSize == 4) { List<uint> uintList = new List<uint>(); for (int i = 0; i < attributes.Count; i++) uintList.Add(Convert.ToUInt32(attributes[i])); if (Platform.StructPackingSize == 0) { List<HighLevelAPI40.ObjectAttribute> hlaAttributes = _session40.GetAttributeValue(objectHandle.ObjectHandle40, uintList); return ObjectAttribute.ConvertFromHighLevelAPI40List(hlaAttributes); } else { List<HighLevelAPI41.ObjectAttribute> hlaAttributes = _session41.GetAttributeValue(objectHandle.ObjectHandle41, uintList); return ObjectAttribute.ConvertFromHighLevelAPI41List(hlaAttributes); } } else { if (Platform.StructPackingSize == 0) { List<HighLevelAPI80.ObjectAttribute> hlaAttributes = _session80.GetAttributeValue(objectHandle.ObjectHandle80, attributes); return ObjectAttribute.ConvertFromHighLevelAPI80List(hlaAttributes); } else { List<HighLevelAPI81.ObjectAttribute> hlaAttributes = _session81.GetAttributeValue(objectHandle.ObjectHandle81, attributes); return ObjectAttribute.ConvertFromHighLevelAPI81List(hlaAttributes); } } }
/// <summary> /// Signs and encrypts data /// </summary> /// <param name="signingMechanism">Signing mechanism</param> /// <param name="signingKeyHandle">Handle of the signing key</param> /// <param name="encryptionMechanism">Encryption mechanism</param> /// <param name="encryptionKeyHandle">Handle of the encryption key</param> /// <param name="inputStream">Input stream from which data to be processed should be read</param> /// <param name="outputStream">Output stream where encrypted data should be written</param> /// <param name="bufferLength">Size of read buffer in bytes</param> /// <returns>Signature</returns> public byte[] SignEncrypt(Mechanism signingMechanism, ObjectHandle signingKeyHandle, Mechanism encryptionMechanism, ObjectHandle encryptionKeyHandle, Stream inputStream, Stream outputStream, int bufferLength) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (signingMechanism == null) throw new ArgumentNullException("signingMechanism"); if (signingKeyHandle == null) throw new ArgumentNullException("signingKeyHandle"); if (encryptionMechanism == null) throw new ArgumentNullException("encryptionMechanism"); if (encryptionKeyHandle == null) throw new ArgumentNullException("encryptionKeyHandle"); if (inputStream == null) throw new ArgumentNullException("inputStream"); if (outputStream == null) throw new ArgumentNullException("outputStream"); if (bufferLength < 1) throw new ArgumentException("Value has to be positive number", "bufferLength"); if (Platform.UnmanagedLongSize == 4) { if (Platform.StructPackingSize == 0) return _session40.SignEncrypt(signingMechanism.Mechanism40, signingKeyHandle.ObjectHandle40, encryptionMechanism.Mechanism40, encryptionKeyHandle.ObjectHandle40, inputStream, outputStream, bufferLength); else return _session41.SignEncrypt(signingMechanism.Mechanism41, signingKeyHandle.ObjectHandle41, encryptionMechanism.Mechanism41, encryptionKeyHandle.ObjectHandle41, inputStream, outputStream, bufferLength); } else { if (Platform.StructPackingSize == 0) return _session80.SignEncrypt(signingMechanism.Mechanism80, signingKeyHandle.ObjectHandle80, encryptionMechanism.Mechanism80, encryptionKeyHandle.ObjectHandle80, inputStream, outputStream, bufferLength); else return _session81.SignEncrypt(signingMechanism.Mechanism81, signingKeyHandle.ObjectHandle81, encryptionMechanism.Mechanism81, encryptionKeyHandle.ObjectHandle81, inputStream, outputStream, bufferLength); } }
/// <summary> /// Encrypts multi-part data /// </summary> /// <param name="mechanism">Encryption mechanism</param> /// <param name="keyHandle">Handle of the encryption key</param> /// <param name="inputStream">Input stream from which data to be encrypted should be read</param> /// <param name="outputStream">Output stream where encrypted data should be written</param> public void Encrypt(Mechanism mechanism, ObjectHandle keyHandle, Stream inputStream, Stream outputStream) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (mechanism == null) throw new ArgumentNullException("mechanism"); if (keyHandle == null) throw new ArgumentNullException("keyHandle"); if (inputStream == null) throw new ArgumentNullException("inputStream"); if (outputStream == null) throw new ArgumentNullException("outputStream"); Encrypt(mechanism, keyHandle, inputStream, outputStream, 4096); }
/// <summary> /// Decrypts data and verifies a signature of data /// </summary> /// <param name="verificationMechanism">Verification mechanism</param> /// <param name="verificationKeyHandle">Handle of the verification key</param> /// <param name="decryptionMechanism">Decryption mechanism</param> /// <param name="decryptionKeyHandle">Handle of the decryption key</param> /// <param name="data">Data to be processed</param> /// <param name="signature">Signature</param> /// <param name="decryptedData">Decrypted data</param> /// <param name="isValid">Flag indicating whether signature is valid</param> public void DecryptVerify(Mechanism verificationMechanism, ObjectHandle verificationKeyHandle, Mechanism decryptionMechanism, ObjectHandle decryptionKeyHandle, byte[] data, byte[] signature, out byte[] decryptedData, out bool isValid) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (verificationMechanism == null) throw new ArgumentNullException("verificationMechanism"); if (verificationKeyHandle == null) throw new ArgumentNullException("verificationKeyHandle"); if (decryptionMechanism == null) throw new ArgumentNullException("decryptionMechanism"); if (decryptionKeyHandle == null) throw new ArgumentNullException("decryptionKeyHandle"); if (data == null) throw new ArgumentNullException("data"); if (signature == null) throw new ArgumentNullException("signature"); using (MemoryStream inputMemoryStream = new MemoryStream(data), outputMemorySteam = new MemoryStream()) { DecryptVerify(verificationMechanism, verificationKeyHandle, decryptionMechanism, decryptionKeyHandle, inputMemoryStream, outputMemorySteam, signature, out isValid); decryptedData = outputMemorySteam.ToArray(); } }
/// <summary> /// Decrypts single-part data /// </summary> /// <param name="mechanism">Decryption mechanism</param> /// <param name="keyHandle">Handle of the decryption key</param> /// <param name="encryptedData">Data to be decrypted</param> /// <returns>Decrypted data</returns> public byte[] Decrypt(Mechanism mechanism, ObjectHandle keyHandle, byte[] encryptedData) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (mechanism == null) throw new ArgumentNullException("mechanism"); if (keyHandle == null) throw new ArgumentNullException("keyHandle"); if (encryptedData == null) throw new ArgumentNullException("encryptedData"); if (Platform.UnmanagedLongSize == 4) { if (Platform.StructPackingSize == 0) return _session40.Decrypt(mechanism.Mechanism40, keyHandle.ObjectHandle40, encryptedData); else return _session41.Decrypt(mechanism.Mechanism41, keyHandle.ObjectHandle41, encryptedData); } else { if (Platform.StructPackingSize == 0) return _session80.Decrypt(mechanism.Mechanism80, keyHandle.ObjectHandle80, encryptedData); else return _session81.Decrypt(mechanism.Mechanism81, keyHandle.ObjectHandle81, encryptedData); } }
/// <summary> /// Decrypts data and verifies a signature of data /// </summary> /// <param name="verificationMechanism">Verification mechanism</param> /// <param name="verificationKeyHandle">Handle of the verification key</param> /// <param name="decryptionMechanism">Decryption mechanism</param> /// <param name="decryptionKeyHandle">Handle of the decryption key</param> /// <param name="inputStream">Input stream from which data to be processed should be read</param> /// <param name="outputStream">Output stream where decrypted data should be written</param> /// <param name="signature">Signature</param> /// <param name="isValid">Flag indicating whether signature is valid</param> public void DecryptVerify(Mechanism verificationMechanism, ObjectHandle verificationKeyHandle, Mechanism decryptionMechanism, ObjectHandle decryptionKeyHandle, Stream inputStream, Stream outputStream, byte[] signature, out bool isValid) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); if (verificationMechanism == null) throw new ArgumentNullException("verificationMechanism"); if (verificationKeyHandle == null) throw new ArgumentNullException("verificationKeyHandle"); if (decryptionMechanism == null) throw new ArgumentNullException("decryptionMechanism"); if (decryptionKeyHandle == null) throw new ArgumentNullException("decryptionKeyHandle"); if (inputStream == null) throw new ArgumentNullException("inputStream"); if (outputStream == null) throw new ArgumentNullException("outputStream"); if (signature == null) throw new ArgumentNullException("signature"); DecryptVerify(verificationMechanism, verificationKeyHandle, decryptionMechanism, decryptionKeyHandle, inputStream, outputStream, signature, out isValid, 4096); }