Class representing a logical connection between an application and a token
Inheritance: IDisposable
        /// <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();
        }
Esempio n. 2
0
        /// <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>
        /// Imports the certificate into the PKCS#11 compatible device and pairs it with the corresponding private key
        /// </summary>
        /// <param name="session">Session with user logged in</param>
        /// <param name="certificate">Certificate that should be imported</param>
        /// <returns>Handle of created certificate object</returns>
        public static ObjectHandle ImportCertificate(Session session, byte[] certificate)
        {
            // Parse certificate
            X509CertificateParser x509CertificateParser = new X509CertificateParser();
            X509Certificate x509Certificate = x509CertificateParser.ReadCertificate(certificate);

            // Get public key from certificate
            AsymmetricKeyParameter pubKeyParams = x509Certificate.GetPublicKey();
            if (!(pubKeyParams is RsaKeyParameters))
                throw new NotSupportedException("Currently only RSA keys are supported");
            RsaKeyParameters rsaPubKeyParams = (RsaKeyParameters)pubKeyParams;

            // Find corresponding private key
            List<ObjectAttribute> privKeySearchTemplate = new List<ObjectAttribute>();
            privKeySearchTemplate.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_PRIVATE_KEY));
            privKeySearchTemplate.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_RSA));
            privKeySearchTemplate.Add(new ObjectAttribute(CKA.CKA_MODULUS, rsaPubKeyParams.Modulus.ToByteArrayUnsigned()));
            privKeySearchTemplate.Add(new ObjectAttribute(CKA.CKA_PUBLIC_EXPONENT, rsaPubKeyParams.Exponent.ToByteArrayUnsigned()));

            List<ObjectHandle> foundObjects = session.FindAllObjects(privKeySearchTemplate);
            if (foundObjects.Count != 1)
                throw new ObjectNotFoundException("Corresponding RSA private key not found");

            ObjectHandle privKeyObjectHandle = foundObjects[0];

            // Read CKA_LABEL and CKA_ID attributes of private key
            List<CKA> privKeyAttrsToRead = new List<CKA>();
            privKeyAttrsToRead.Add(CKA.CKA_LABEL);
            privKeyAttrsToRead.Add(CKA.CKA_ID);

            List<ObjectAttribute> privKeyAttributes = session.GetAttributeValue(privKeyObjectHandle, privKeyAttrsToRead);

            // Define attributes of new certificate object
            List<ObjectAttribute> certificateAttributes = new List<ObjectAttribute>();
            certificateAttributes.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_CERTIFICATE));
            certificateAttributes.Add(new ObjectAttribute(CKA.CKA_TOKEN, true));
            certificateAttributes.Add(new ObjectAttribute(CKA.CKA_PRIVATE, false));
            certificateAttributes.Add(new ObjectAttribute(CKA.CKA_MODIFIABLE, true));
            certificateAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, privKeyAttributes[0].GetValueAsString()));
            certificateAttributes.Add(new ObjectAttribute(CKA.CKA_CERTIFICATE_TYPE, CKC.CKC_X_509));
            certificateAttributes.Add(new ObjectAttribute(CKA.CKA_TRUSTED, false));
            certificateAttributes.Add(new ObjectAttribute(CKA.CKA_SUBJECT, x509Certificate.SubjectDN.GetDerEncoded()));
            certificateAttributes.Add(new ObjectAttribute(CKA.CKA_ID, privKeyAttributes[1].GetValueAsByteArray()));
            certificateAttributes.Add(new ObjectAttribute(CKA.CKA_ISSUER, x509Certificate.IssuerDN.GetDerEncoded()));
            certificateAttributes.Add(new ObjectAttribute(CKA.CKA_SERIAL_NUMBER, new DerInteger(x509Certificate.SerialNumber).GetDerEncoded()));
            certificateAttributes.Add(new ObjectAttribute(CKA.CKA_VALUE, x509Certificate.GetEncoded()));

            // Create certificate object
            return session.CreateObject(certificateAttributes);
        }
        /// <summary>
        /// Imports trusted certificate into the PKCS#11 compatible device
        /// </summary>
        /// <param name="session">Session with user logged in</param>
        /// <param name="certificate">Certificate that should be imported</param>
        /// <returns>Handle of created certificate object</returns>
        public static ObjectHandle ImportTrustedCertificate(Session session, byte[] certificate)
        {
            // Choose unique values for CKA_LABEL and CKA_ID attributes
            string ckaLabel = Guid.NewGuid().ToString();
            byte[] ckaId = session.GenerateRandom(20);

            return ImportTrustedCertificate(session, certificate, ckaLabel, ckaId);
        }
        /// <summary>
        /// Imports trusted certificate into the PKCS#11 compatible device
        /// </summary>
        /// <param name="session">Session with user logged in</param>
        /// <param name="certificate">Certificate that should be imported</param>
        /// <param name="ckaLabel">Value of CKA_LABEL attribute</param>
        /// <param name="ckaId">Value of CKA_ID attribute</param>
        /// <returns>Handle of created certificate object</returns>
        public static ObjectHandle ImportTrustedCertificate(Session session, byte[] certificate, string ckaLabel, byte[] ckaId)
        {
            // Parse certificate
            X509CertificateParser x509CertificateParser = new X509CertificateParser();
            X509Certificate x509Certificate = x509CertificateParser.ReadCertificate(certificate);

            // Define attributes of new certificate object
            List<ObjectAttribute> certificateAttributes = new List<ObjectAttribute>();
            certificateAttributes.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_CERTIFICATE));
            certificateAttributes.Add(new ObjectAttribute(CKA.CKA_TOKEN, true));
            certificateAttributes.Add(new ObjectAttribute(CKA.CKA_PRIVATE, false));
            certificateAttributes.Add(new ObjectAttribute(CKA.CKA_MODIFIABLE, true));
            certificateAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, ckaLabel));
            certificateAttributes.Add(new ObjectAttribute(CKA.CKA_CERTIFICATE_TYPE, CKC.CKC_X_509));
            certificateAttributes.Add(new ObjectAttribute(CKA.CKA_TRUSTED, true));
            certificateAttributes.Add(new ObjectAttribute(CKA.CKA_SUBJECT, x509Certificate.SubjectDN.GetDerEncoded()));
            certificateAttributes.Add(new ObjectAttribute(CKA.CKA_ID, ckaId));
            certificateAttributes.Add(new ObjectAttribute(CKA.CKA_ISSUER, x509Certificate.IssuerDN.GetDerEncoded()));
            certificateAttributes.Add(new ObjectAttribute(CKA.CKA_SERIAL_NUMBER, new DerInteger(x509Certificate.SerialNumber).GetDerEncoded()));
            certificateAttributes.Add(new ObjectAttribute(CKA.CKA_VALUE, x509Certificate.GetEncoded()));

            // Create certificate object
            return session.CreateObject(certificateAttributes);
        }
Esempio n. 6
0
 /// <summary>
 /// Creates the data object.
 /// </summary>
 /// <param name='session'>Read-write session with user logged in</param>
 /// <returns>Object handle</returns>
 public static ObjectHandle CreateDataObject(Session session)
 {
     // Prepare attribute template of new data object
     List<ObjectAttribute> objectAttributes = new List<ObjectAttribute>();
     objectAttributes.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_DATA));
     objectAttributes.Add(new ObjectAttribute(CKA.CKA_TOKEN, true));
     objectAttributes.Add(new ObjectAttribute(CKA.CKA_APPLICATION, Settings.ApplicationName));
     objectAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, Settings.ApplicationName));
     objectAttributes.Add(new ObjectAttribute(CKA.CKA_VALUE, "Data object content"));
     
     // Create object
     return session.CreateObject(objectAttributes);
 }
Esempio n. 7
0
 /// <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);
 }
Esempio n. 8
0
 /// <summary>
 /// Generates symetric key.
 /// </summary>
 /// <param name='session'>Read-write session with user logged in</param>
 /// <returns>Object handle</returns>
 public static ObjectHandle GenerateKey(Session session)
 {
     // Prepare attribute template of new key
     List<ObjectAttribute> objectAttributes = new List<ObjectAttribute>();
     objectAttributes.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY));
     objectAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES3));
     objectAttributes.Add(new ObjectAttribute(CKA.CKA_ENCRYPT, true));
     objectAttributes.Add(new ObjectAttribute(CKA.CKA_DECRYPT, true));
     objectAttributes.Add(new ObjectAttribute(CKA.CKA_DERIVE, true));
     objectAttributes.Add(new ObjectAttribute(CKA.CKA_EXTRACTABLE, true));
     
     // Specify key generation mechanism
     Mechanism mechanism = new Mechanism(CKM.CKM_DES3_KEY_GEN);
     
     // Generate key
     return session.GenerateKey(mechanism, objectAttributes);
 }
        /// <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>
        /// 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;
            }
        }
Esempio n. 11
0
        /// <summary>
        /// Closes a session between an application and a token
        /// </summary>
        /// <param name="session">Session</param>
        public void CloseSession(Session session)
        {
            if (session == null)
                throw new ArgumentNullException("session");

            session.CloseSession();
        }