/// <summary>
        /// Verifies the data given as parameter with the given public key.
        /// </summary>
        /// <remarks>
        /// <para>The function calculates a message digest over the given signature
        /// data and verifies the digest with the digest stored in the
        /// signature packet.</para>
        /// <para>The results of the verify operation are directly stored
        /// in the SignatureStatus property of this class.</para>
        /// </remarks>
        /// <param name="bSignedData">The data that is to be verified.</param>
        /// <param name="pkpKey">The key that is to verify the signature</param>
        public void Verify(byte[] bSignedData, PublicKeyPacket pkpKey)
        {
            System.Security.Cryptography.HashAlgorithm haVerifyer;
            AsymmetricCipher acVerifyer;

            switch (this.HashAlgorithm) {
                case HashAlgorithms.MD5:
                    haVerifyer = System.Security.Cryptography.MD5.Create();
                    break;
                case HashAlgorithms.SHA1:
                    haVerifyer = System.Security.Cryptography.SHA1.Create();
                    break;
                default:
                    throw(new System.Exception("Currently only MD5 and SHA1 are implemented as hash algorithms!"));
            }

            switch (this.SignatureAlgorithm) {
                case AsymAlgorithms.DSA:
                    acVerifyer = new SharpPrivacy.SharpPrivacyLib.Cipher.DSA();
                    break;
                case AsymAlgorithms.RSA_Encrypt_Sign:
                case AsymAlgorithms.RSA_Sign_Only:
                    acVerifyer = new SharpPrivacy.SharpPrivacyLib.Cipher.RSA();
                    break;
                default:
                    throw(new System.Exception("Currently only DSA and RSA are implemented as signature algorithms!"));
            }

            byte[] bSignature = new byte[0];
            int iCounter = 0;
            if (this.Version <= SignaturePacketVersionNumbers.v3) {
                bSignature = new byte[5];

                bSignature[iCounter++] = (byte)this.SignatureType;
                long lTime = (dtTimeCreated.Ticks - new DateTime(1970, 1, 1).Ticks)/10000000;
                bSignature[iCounter++] = (byte)((lTime >> 24) & 0xFF);
                bSignature[iCounter++] = (byte)((lTime >> 16) & 0xFF);
                bSignature[iCounter++] = (byte)((lTime >> 8) & 0xFF);
                bSignature[iCounter++] = (byte)(lTime & 0xFF);
            } else {
                //Hashed Subpackets Length
                int lHashedSubPacketLength = 0;
                for (int i=0; i<this.HashedSubPackets.Length; i++) {
                    lHashedSubPacketLength += this.HashedSubPackets[i].Generate().Length;
                }

                bSignature = new byte[lHashedSubPacketLength + 12];
                bSignature[iCounter++] = 4; // Version
                bSignature[iCounter++] = (byte)this.SignatureType;
                bSignature[iCounter++] = (byte)this.SignatureAlgorithm;
                bSignature[iCounter++] = (byte)this.HashAlgorithm;

                //Hashed Subpackets
                bSignature[iCounter++] = (byte)((lHashedSubPacketLength >> 8) & 0xFF);
                bSignature[iCounter++] = (byte)(lHashedSubPacketLength & 0xFF);
                for (int i=0; i<this.HashedSubPackets.Length; i++) {
                    byte[] bSubPacket = this.HashedSubPackets[i].Generate();
                    Array.Copy(bSubPacket, 0, bSignature, iCounter, bSubPacket.Length);
                    iCounter += bSubPacket.Length;
                }

                //Final Trailer of 6 bytes
                bSignature[iCounter++] = 0x04;
                bSignature[iCounter++] = 0xFF;
                bSignature[iCounter++] = (byte)(((lHashedSubPacketLength+6) >> 24) & 0xFF);
                bSignature[iCounter++] = (byte)(((lHashedSubPacketLength+6) >> 16) & 0xFF);
                bSignature[iCounter++] = (byte)(((lHashedSubPacketLength+6) >> 8) & 0xFF);
                bSignature[iCounter++] = (byte)((lHashedSubPacketLength+6) & 0xFF);

            }

            byte[] bData = new byte[bSignedData.Length + bSignature.Length];
            Array.Copy(bSignedData, bData, bSignedData.Length);
            Array.Copy(bSignature, 0, bData, bSignedData.Length, bSignature.Length);

            byte[] bHash = haVerifyer.ComputeHash(bData);
            BigInteger biHash = new BigInteger(bHash);

            //PKCS1 Encode the hash
            if (this.SignatureAlgorithm != AsymAlgorithms.DSA) {

                // We encode the MD in this way:
                //  0  A PAD(n bytes)   0  ASN(asnlen bytes)  MD(len bytes)
                // PAD consists of FF bytes.
                byte[] bASN = new byte[0];

                switch (this.HashAlgorithm) {
                    case HashAlgorithms.MD5:
                        bASN = new byte[] {0x30, 0x20, 0x30, 0x0C, 0x06, 0x08,
                                           0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D,
                                           0x02, 0x05, 0x05, 0x00, 0x04, 0x10};
                        break;
                    case HashAlgorithms.SHA1:
                        bASN = new byte[] {0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
                                           0x2b, 0x0E, 0x03, 0x02, 0x1A, 0x05,
                                           0x00, 0x04, 0x14};
                        break;
                }

                int iFrameSize = (pkpKey.KeyMaterial[0].bitCount() + 7) / 8;
                byte[] bFrame = new byte[iFrameSize];
                int iASNCounter = 0;

                bFrame[iASNCounter++] = 0;
                bFrame[iASNCounter++] = 1;
                int iFFLength = iFrameSize - bHash.Length - bASN.Length - 3;
                for (int i=0; i<iFFLength; i++) {
                    bFrame[iASNCounter++] = 0xFF;
                }
                bFrame[iASNCounter++] = 0;
                Array.Copy(bASN, 0, bFrame, iASNCounter, bASN.Length);
                iASNCounter += bASN.Length;
                Array.Copy(bHash, 0, bFrame, iASNCounter, bHash.Length);
                biHash = new BigInteger(bFrame);
            }

            if (acVerifyer.Verify(this.Signature, biHash, pkpKey)) {
                ssSignatureStatus = SignatureStatusTypes.Valid;
            } else {
                ssSignatureStatus = SignatureStatusTypes.Invalid;
            }
        }
 private BigInteger[][] GenerateRSAEncryptionKey(int iKeySize)
 {
     RSA rsaKeyGenerator = new RSA();
     BigInteger[][] biEncryptionKey = rsaKeyGenerator.Generate(iKeySize);
     return biEncryptionKey;
 }
        /// <summary>
        /// Signes the data given as parameter with the given secret key.
        /// The given password has to fit the given key.
        /// </summary>
        /// <remarks>
        /// <para>The function calculates a message digest over the given signature
        /// data and signes the digest with the given key.</para>
        /// <para>The results of the signature operation are directly stored
        /// in the Signature property of this class.</para>
        /// </remarks>
        /// <param name="bSignedData">The data that is to be signed.</param>
        /// <param name="skpKey">The key that is to sign the data</param>
        /// <param name="strPassphrase">The passphrase that is neccessary to
        /// decrypt the given key.</param>
        public void Sign(byte[] bSignedData, SecretKeyPacket skpKey, string strPassphrase)
        {
            System.Security.Cryptography.HashAlgorithm haSigner;
            AsymmetricCipher acSigner;

            this.SignatureAlgorithm = skpKey.PublicKey.Algorithm;

            switch (this.HashAlgorithm) {
                case HashAlgorithms.MD5:
                    haSigner = System.Security.Cryptography.MD5.Create();
                    break;
                case HashAlgorithms.SHA1:
                    haSigner = System.Security.Cryptography.SHA1.Create();
                    break;
                default:
                    throw(new System.Exception("Currently only MD5 and SHA1 are implemented as hash algorithms!"));
            }

            switch (this.SignatureAlgorithm) {
                case AsymAlgorithms.DSA:
                    acSigner = new SharpPrivacy.SharpPrivacyLib.Cipher.DSA();
                    break;
                case AsymAlgorithms.RSA_Encrypt_Sign:
                case AsymAlgorithms.RSA_Sign_Only:
                    acSigner = new SharpPrivacy.SharpPrivacyLib.Cipher.RSA();
                    break;
                default:
                    throw(new System.Exception("Currently only DSA and RSA are implemented as signature algorithms!"));
            }

            byte[] bSignature = new byte[0];
            int iCounter = 0;
            if (this.Version <= SignaturePacketVersionNumbers.v3) {
                bSignature = new byte[5];

                bSignature[iCounter++] = (byte)this.SignatureType;
                long lTime = (dtTimeCreated.Ticks - new DateTime(1970, 1, 1).Ticks)/10000000;
                bSignature[iCounter++] = (byte)((lTime >> 24) & 0xFF);
                bSignature[iCounter++] = (byte)((lTime >> 16) & 0xFF);
                bSignature[iCounter++] = (byte)((lTime >> 8) & 0xFF);
                bSignature[iCounter++] = (byte)(lTime & 0xFF);
            } else {

                // Add Issuer KeyID Subpacket if it's not there.
                try {
                    ulong lTestForKeyID = this.KeyID;
                } catch (Exception) {
                    SignatureSubPacket sspIssuerKeyID = new SignatureSubPacket();
                    sspIssuerKeyID.Type = SignatureSubPacketTypes.IssuerKeyID;
                    sspIssuerKeyID.KeyID = this.lKeyID;
                    this.AddSubPacket(sspIssuerKeyID, true);
                }

                // Add TimeCreated Subpacket if it's not there.
                try {
                    this.FindSignatureCreationTime();
                } catch (Exception) {
                    SignatureSubPacket sspCreationTime = new SignatureSubPacket();
                    sspCreationTime.Type = SignatureSubPacketTypes.SignatureCreationTime;
                    sspCreationTime.TimeCreated = DateTime.Now;
                    this.AddSubPacket(sspCreationTime, true);
                }

                //Hashed Subpackets Length
                int lHashedSubPacketLength = 0;
                for (int i=0; i<this.HashedSubPackets.Length; i++) {
                    lHashedSubPacketLength += this.HashedSubPackets[i].Generate().Length;
                }

                bSignature = new byte[lHashedSubPacketLength + 12];
                bSignature[iCounter++] = 4; // Version
                bSignature[iCounter++] = (byte)this.SignatureType;
                bSignature[iCounter++] = (byte)this.SignatureAlgorithm;
                bSignature[iCounter++] = (byte)this.HashAlgorithm;

                //Hashed
                bSignature[iCounter++] = (byte)((lHashedSubPacketLength >> 8) & 0xFF);
                bSignature[iCounter++] = (byte)(lHashedSubPacketLength & 0xFF);
                for (int i=0; i<this.HashedSubPackets.Length; i++) {
                    byte[] bSubPacket = this.HashedSubPackets[i].Generate();
                    Array.Copy(bSubPacket, 0, bSignature, iCounter, bSubPacket.Length);
                    iCounter += bSubPacket.Length;
                }

                //Final Trailer of 6 bytes
                bSignature[iCounter++] = 0x04;
                bSignature[iCounter++] = 0xFF;
                bSignature[iCounter++] = (byte)(((lHashedSubPacketLength+6) >> 24) & 0xFF);
                bSignature[iCounter++] = (byte)(((lHashedSubPacketLength+6) >> 16) & 0xFF);
                bSignature[iCounter++] = (byte)(((lHashedSubPacketLength+6) >> 8) & 0xFF);
                bSignature[iCounter++] = (byte)((lHashedSubPacketLength+6) & 0xFF);
            }

            byte[] bData = new byte[bSignedData.Length + bSignature.Length];
            Array.Copy(bSignedData, bData, bSignedData.Length);
            Array.Copy(bSignature, 0, bData, bSignedData.Length, bSignature.Length);

            byte[] bHash = haSigner.ComputeHash(bData);
            BigInteger biHash = new BigInteger(bHash);

            //PKCS1 Encode the hash
            if (this.SignatureAlgorithm != AsymAlgorithms.DSA) {

                // We encode the MD in this way:
                //  0  A PAD(n bytes)   0  ASN(asnlen bytes)  MD(len bytes)
                // PAD consists of FF bytes.
                byte[] bASN = new byte[0];

                switch (this.HashAlgorithm) {
                    case HashAlgorithms.MD5:
                        bASN = new byte[] {0x30, 0x20, 0x30, 0x0C, 0x06, 0x08,
                                           0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D,
                                           0x02, 0x05, 0x05, 0x00, 0x04, 0x10};
                        break;
                    case HashAlgorithms.SHA1:
                        bASN = new byte[] {0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
                                           0x2b, 0x0E, 0x03, 0x02, 0x1A, 0x05,
                                           0x00, 0x04, 0x14};
                        break;
                }

                int iFrameSize = (skpKey.PublicKey.KeyMaterial[0].bitCount() + 7) / 8;
                byte[] bFrame = new byte[iFrameSize];
                int iASNCounter = 0;

                bFrame[iASNCounter++] = 0;
                bFrame[iASNCounter++] = 1;
                int iFFLength = iFrameSize - bHash.Length - bASN.Length - 3;
                for (int i=0; i<iFFLength; i++)
                    bFrame[iASNCounter++] = 0xFF;

                bFrame[iASNCounter++] = 0;
                Array.Copy(bASN, 0, bFrame, iASNCounter, bASN.Length);
                iASNCounter += bASN.Length;
                Array.Copy(bHash, 0, bFrame, iASNCounter, bHash.Length);
                biHash = new BigInteger(bFrame);
            }

            sSignedHash16Bit = (ushort)((bHash[0] << 8) + bHash[1]);
            biSignature = acSigner.Sign(biHash, skpKey, strPassphrase);
            this.bIsUpdated = true;
        }
        /// <summary>
        /// Encryptes the session key stored in the SessionKey property
        /// and saves the results in the EncryptedSessionKey property.
        /// </summary>
        /// <remarks>This method also calles EncodeSessionKey so that it
        /// does not have been called before calling EncryptSessionKey.
        /// <p></p>
        /// Please note: calling this function takes some time, because
        /// asymmetrical encryption takes some time!
        /// </remarks>
        /// <param name="pkpPacket">An PublicKeyPacket to which
        /// the sessionkey should be encrypted to.</param>
        public void EncryptSessionKey(PublicKeyPacket pkpPacket)
        {
            EncodeSessionKey(pkpPacket.KeyMaterial[0].bitCount());

            AsymmetricCipher acCipher = new RSA();
            switch (aaPublicAlgorithm) {
                case AsymAlgorithms.ElGama_Encrypt_Sign:
                case AsymAlgorithms.ElGamal_Encrypt_Only:
                    acCipher = new ElGamal();
                    break;

                case AsymAlgorithms.RSA_Encrypt_Only:
                case AsymAlgorithms.RSA_Encrypt_Sign:
                    acCipher = new RSA();
                    break;

                default:
                    throw new System.Exception("The chosen public key algorithm is not yet implemented!");
            }

            this.bIsUpdated = true;
            biEncryptedSessionKey = acCipher.Encrypt(new BigInteger(this.bEncodedSessionKey), pkpPacket);
        }
        /// <summary>
        /// Decrypts the session key stored in the EncryptedSessionKey
        /// property and saves the decrypted key in the EncodedSessionKey
        /// property.
        /// </summary>
        /// <remarks>This function also calls DecodeSessionKey so that the
        /// decrypted and decoded sessionkey is stored in the
        /// SessionKey property.</remarks>
        /// <param name="tskKey">A transportable secret key that is used to
        /// decrypt the encrypted session key.</param>
        /// <param name="strPassphrase">The passphrase used to decrypt the
        /// encrypted key material of the given transportable secret
        /// key.</param>
        public void DecryptSessionKey(TransportableSecretKey tskKey, string strPassphrase)
        {
            AsymmetricCipher acCipher = new RSA();
            switch (aaPublicAlgorithm) {
                case AsymAlgorithms.ElGama_Encrypt_Sign:
                case AsymAlgorithms.ElGamal_Encrypt_Only:
                    acCipher = new ElGamal();
                    break;

                case AsymAlgorithms.RSA_Encrypt_Only:
                case AsymAlgorithms.RSA_Encrypt_Sign:
                    acCipher = new RSA();
                    break;

                default:
                    throw new System.Exception("The chosen public key algorithm is not yet implemented!");
            }

            bool bFound = false;
            SecretKeyPacket skpKey = new SecretKeyPacket();
            IEnumerator ieSubkeys = tskKey.SubKeys.GetEnumerator();
            while (ieSubkeys.MoveNext()) {
                if (!(ieSubkeys.Current is SecretKeyPacket))
                    throw new System.Exception("Expected a secret key packet, but did not find one!");

                skpKey = (SecretKeyPacket)ieSubkeys.Current;
                if (skpKey.PublicKey.KeyID == lKeyID) {
                    bFound = true;
                    continue;
                }
            }

            // check if the message was encrypted with the primary key
            if (!bFound) {
                if (tskKey.PrimaryKey.PublicKey.KeyID == lKeyID) {
                    skpKey = tskKey.PrimaryKey;
                } else {
                    //theoretically we should never see this exception, as
                    //encrytped message makes sure we only get fitting secret
                    //keys, but just in case someone calls this directly, we
                    //throw an exception
                    throw new System.Exception("No fitting secret key found!");
                }
            }

            BigInteger biKey = acCipher.Decrypt(this.biEncryptedSessionKey, skpKey, strPassphrase);

            this.bEncodedSessionKey = biKey.getBytes();
            DecodeSessionKey();
        }
Example #6
0
        /// <summary>
        /// Verifies the data given as parameter with the given public key.
        /// </summary>
        /// <remarks>
        /// <para>The function calculates a message digest over the given signature
        /// data and verifies the digest with the digest stored in the
        /// signature packet.</para>
        /// <para>The results of the verify operation are directly stored
        /// in the SignatureStatus property of this class.</para>
        /// </remarks>
        /// <param name="bSignedData">The data that is to be verified.</param>
        /// <param name="pkpKey">The key that is to verify the signature</param>
        public void Verify(byte[] bSignedData, PublicKeyPacket pkpKey)
        {
            System.Security.Cryptography.HashAlgorithm haVerifyer;
            AsymmetricCipher acVerifyer;

            switch (this.HashAlgorithm)
            {
            case HashAlgorithms.MD5:
                haVerifyer = System.Security.Cryptography.MD5.Create();
                break;

            case HashAlgorithms.SHA1:
                haVerifyer = System.Security.Cryptography.SHA1.Create();
                break;

            default:
                throw(new System.Exception("Currently only MD5 and SHA1 are implemented as hash algorithms!"));
            }

            switch (this.SignatureAlgorithm)
            {
            case AsymAlgorithms.DSA:
                acVerifyer = new SharpPrivacy.SharpPrivacyLib.Cipher.DSA();
                break;

            case AsymAlgorithms.RSA_Encrypt_Sign:
            case AsymAlgorithms.RSA_Sign_Only:
                acVerifyer = new SharpPrivacy.SharpPrivacyLib.Cipher.RSA();
                break;

            default:
                throw(new System.Exception("Currently only DSA and RSA are implemented as signature algorithms!"));
            }

            byte[] bSignature = new byte[0];
            int    iCounter   = 0;

            if (this.Version <= SignaturePacketVersionNumbers.v3)
            {
                bSignature = new byte[5];

                bSignature[iCounter++] = (byte)this.SignatureType;
                long lTime = (dtTimeCreated.Ticks - new DateTime(1970, 1, 1).Ticks) / 10000000;
                bSignature[iCounter++] = (byte)((lTime >> 24) & 0xFF);
                bSignature[iCounter++] = (byte)((lTime >> 16) & 0xFF);
                bSignature[iCounter++] = (byte)((lTime >> 8) & 0xFF);
                bSignature[iCounter++] = (byte)(lTime & 0xFF);
            }
            else
            {
                //Hashed Subpackets Length
                int lHashedSubPacketLength = 0;
                for (int i = 0; i < this.HashedSubPackets.Length; i++)
                {
                    lHashedSubPacketLength += this.HashedSubPackets[i].Generate().Length;
                }

                bSignature             = new byte[lHashedSubPacketLength + 12];
                bSignature[iCounter++] = 4;                 // Version
                bSignature[iCounter++] = (byte)this.SignatureType;
                bSignature[iCounter++] = (byte)this.SignatureAlgorithm;
                bSignature[iCounter++] = (byte)this.HashAlgorithm;

                //Hashed Subpackets
                bSignature[iCounter++] = (byte)((lHashedSubPacketLength >> 8) & 0xFF);
                bSignature[iCounter++] = (byte)(lHashedSubPacketLength & 0xFF);
                for (int i = 0; i < this.HashedSubPackets.Length; i++)
                {
                    byte[] bSubPacket = this.HashedSubPackets[i].Generate();
                    Array.Copy(bSubPacket, 0, bSignature, iCounter, bSubPacket.Length);
                    iCounter += bSubPacket.Length;
                }

                //Final Trailer of 6 bytes
                bSignature[iCounter++] = 0x04;
                bSignature[iCounter++] = 0xFF;
                bSignature[iCounter++] = (byte)(((lHashedSubPacketLength + 6) >> 24) & 0xFF);
                bSignature[iCounter++] = (byte)(((lHashedSubPacketLength + 6) >> 16) & 0xFF);
                bSignature[iCounter++] = (byte)(((lHashedSubPacketLength + 6) >> 8) & 0xFF);
                bSignature[iCounter++] = (byte)((lHashedSubPacketLength + 6) & 0xFF);
            }

            byte[] bData = new byte[bSignedData.Length + bSignature.Length];
            Array.Copy(bSignedData, bData, bSignedData.Length);
            Array.Copy(bSignature, 0, bData, bSignedData.Length, bSignature.Length);

            byte[]     bHash  = haVerifyer.ComputeHash(bData);
            BigInteger biHash = new BigInteger(bHash);

            //PKCS1 Encode the hash
            if (this.SignatureAlgorithm != AsymAlgorithms.DSA)
            {
                // We encode the MD in this way:
                //  0  A PAD(n bytes)   0  ASN(asnlen bytes)  MD(len bytes)
                // PAD consists of FF bytes.
                byte[] bASN = new byte[0];

                switch (this.HashAlgorithm)
                {
                case HashAlgorithms.MD5:
                    bASN = new byte[] { 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08,
                                        0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D,
                                        0x02, 0x05, 0x05, 0x00, 0x04, 0x10 };
                    break;

                case HashAlgorithms.SHA1:
                    bASN = new byte[] { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
                                        0x2b, 0x0E, 0x03, 0x02, 0x1A, 0x05,
                                        0x00, 0x04, 0x14 };
                    break;
                }

                int    iFrameSize  = (pkpKey.KeyMaterial[0].bitCount() + 7) / 8;
                byte[] bFrame      = new byte[iFrameSize];
                int    iASNCounter = 0;

                bFrame[iASNCounter++] = 0;
                bFrame[iASNCounter++] = 1;
                int iFFLength = iFrameSize - bHash.Length - bASN.Length - 3;
                for (int i = 0; i < iFFLength; i++)
                {
                    bFrame[iASNCounter++] = 0xFF;
                }
                bFrame[iASNCounter++] = 0;
                Array.Copy(bASN, 0, bFrame, iASNCounter, bASN.Length);
                iASNCounter += bASN.Length;
                Array.Copy(bHash, 0, bFrame, iASNCounter, bHash.Length);
                biHash = new BigInteger(bFrame);
            }

            if (acVerifyer.Verify(this.Signature, biHash, pkpKey))
            {
                ssSignatureStatus = SignatureStatusTypes.Valid;
            }
            else
            {
                ssSignatureStatus = SignatureStatusTypes.Invalid;
            }
        }
Example #7
0
        /// <summary>
        /// Signes the data given as parameter with the given secret key.
        /// The given password has to fit the given key.
        /// </summary>
        /// <remarks>
        /// <para>The function calculates a message digest over the given signature
        /// data and signes the digest with the given key.</para>
        /// <para>The results of the signature operation are directly stored
        /// in the Signature property of this class.</para>
        /// </remarks>
        /// <param name="bSignedData">The data that is to be signed.</param>
        /// <param name="skpKey">The key that is to sign the data</param>
        /// <param name="strPassphrase">The passphrase that is neccessary to
        /// decrypt the given key.</param>
        public void Sign(byte[] bSignedData, SecretKeyPacket skpKey, string strPassphrase)
        {
            System.Security.Cryptography.HashAlgorithm haSigner;
            AsymmetricCipher acSigner;

            this.SignatureAlgorithm = skpKey.PublicKey.Algorithm;

            switch (this.HashAlgorithm)
            {
            case HashAlgorithms.MD5:
                haSigner = System.Security.Cryptography.MD5.Create();
                break;

            case HashAlgorithms.SHA1:
                haSigner = System.Security.Cryptography.SHA1.Create();
                break;

            default:
                throw(new System.Exception("Currently only MD5 and SHA1 are implemented as hash algorithms!"));
            }

            switch (this.SignatureAlgorithm)
            {
            case AsymAlgorithms.DSA:
                acSigner = new SharpPrivacy.SharpPrivacyLib.Cipher.DSA();
                break;

            case AsymAlgorithms.RSA_Encrypt_Sign:
            case AsymAlgorithms.RSA_Sign_Only:
                acSigner = new SharpPrivacy.SharpPrivacyLib.Cipher.RSA();
                break;

            default:
                throw(new System.Exception("Currently only DSA and RSA are implemented as signature algorithms!"));
            }

            byte[] bSignature = new byte[0];
            int    iCounter   = 0;

            if (this.Version <= SignaturePacketVersionNumbers.v3)
            {
                bSignature = new byte[5];

                bSignature[iCounter++] = (byte)this.SignatureType;
                long lTime = (dtTimeCreated.Ticks - new DateTime(1970, 1, 1).Ticks) / 10000000;
                bSignature[iCounter++] = (byte)((lTime >> 24) & 0xFF);
                bSignature[iCounter++] = (byte)((lTime >> 16) & 0xFF);
                bSignature[iCounter++] = (byte)((lTime >> 8) & 0xFF);
                bSignature[iCounter++] = (byte)(lTime & 0xFF);
            }
            else
            {
                // Add Issuer KeyID Subpacket if it's not there.
                try {
                    ulong lTestForKeyID = this.KeyID;
                } catch (Exception) {
                    SignatureSubPacket sspIssuerKeyID = new SignatureSubPacket();
                    sspIssuerKeyID.Type  = SignatureSubPacketTypes.IssuerKeyID;
                    sspIssuerKeyID.KeyID = this.lKeyID;
                    this.AddSubPacket(sspIssuerKeyID, true);
                }

                // Add TimeCreated Subpacket if it's not there.
                try {
                    this.FindSignatureCreationTime();
                } catch (Exception) {
                    SignatureSubPacket sspCreationTime = new SignatureSubPacket();
                    sspCreationTime.Type        = SignatureSubPacketTypes.SignatureCreationTime;
                    sspCreationTime.TimeCreated = DateTime.Now;
                    this.AddSubPacket(sspCreationTime, true);
                }

                //Hashed Subpackets Length
                int lHashedSubPacketLength = 0;
                for (int i = 0; i < this.HashedSubPackets.Length; i++)
                {
                    lHashedSubPacketLength += this.HashedSubPackets[i].Generate().Length;
                }

                bSignature             = new byte[lHashedSubPacketLength + 12];
                bSignature[iCounter++] = 4;                 // Version
                bSignature[iCounter++] = (byte)this.SignatureType;
                bSignature[iCounter++] = (byte)this.SignatureAlgorithm;
                bSignature[iCounter++] = (byte)this.HashAlgorithm;

                //Hashed
                bSignature[iCounter++] = (byte)((lHashedSubPacketLength >> 8) & 0xFF);
                bSignature[iCounter++] = (byte)(lHashedSubPacketLength & 0xFF);
                for (int i = 0; i < this.HashedSubPackets.Length; i++)
                {
                    byte[] bSubPacket = this.HashedSubPackets[i].Generate();
                    Array.Copy(bSubPacket, 0, bSignature, iCounter, bSubPacket.Length);
                    iCounter += bSubPacket.Length;
                }

                //Final Trailer of 6 bytes
                bSignature[iCounter++] = 0x04;
                bSignature[iCounter++] = 0xFF;
                bSignature[iCounter++] = (byte)(((lHashedSubPacketLength + 6) >> 24) & 0xFF);
                bSignature[iCounter++] = (byte)(((lHashedSubPacketLength + 6) >> 16) & 0xFF);
                bSignature[iCounter++] = (byte)(((lHashedSubPacketLength + 6) >> 8) & 0xFF);
                bSignature[iCounter++] = (byte)((lHashedSubPacketLength + 6) & 0xFF);
            }

            byte[] bData = new byte[bSignedData.Length + bSignature.Length];
            Array.Copy(bSignedData, bData, bSignedData.Length);
            Array.Copy(bSignature, 0, bData, bSignedData.Length, bSignature.Length);

            byte[]     bHash  = haSigner.ComputeHash(bData);
            BigInteger biHash = new BigInteger(bHash);

            //PKCS1 Encode the hash
            if (this.SignatureAlgorithm != AsymAlgorithms.DSA)
            {
                // We encode the MD in this way:
                //  0  A PAD(n bytes)   0  ASN(asnlen bytes)  MD(len bytes)
                // PAD consists of FF bytes.
                byte[] bASN = new byte[0];

                switch (this.HashAlgorithm)
                {
                case HashAlgorithms.MD5:
                    bASN = new byte[] { 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08,
                                        0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D,
                                        0x02, 0x05, 0x05, 0x00, 0x04, 0x10 };
                    break;

                case HashAlgorithms.SHA1:
                    bASN = new byte[] { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
                                        0x2b, 0x0E, 0x03, 0x02, 0x1A, 0x05,
                                        0x00, 0x04, 0x14 };
                    break;
                }

                int    iFrameSize  = (skpKey.PublicKey.KeyMaterial[0].bitCount() + 7) / 8;
                byte[] bFrame      = new byte[iFrameSize];
                int    iASNCounter = 0;

                bFrame[iASNCounter++] = 0;
                bFrame[iASNCounter++] = 1;
                int iFFLength = iFrameSize - bHash.Length - bASN.Length - 3;
                for (int i = 0; i < iFFLength; i++)
                {
                    bFrame[iASNCounter++] = 0xFF;
                }

                bFrame[iASNCounter++] = 0;
                Array.Copy(bASN, 0, bFrame, iASNCounter, bASN.Length);
                iASNCounter += bASN.Length;
                Array.Copy(bHash, 0, bFrame, iASNCounter, bHash.Length);
                biHash = new BigInteger(bFrame);
            }

            sSignedHash16Bit = (ushort)((bHash[0] << 8) + bHash[1]);
            biSignature      = acSigner.Sign(biHash, skpKey, strPassphrase);
            this.bIsUpdated  = true;
        }