| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 | using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Security.Cryptography;using Renci.SshNet.Common;namespace Renci.SshNet.Security.Cryptography{    /// <summary>    /// Implements digital signature where where asymmetric cipher is used,    /// </summary>    public abstract class CipherDigitalSignature : DigitalSignature    {        private AsymmetricCipher _cipher;        private ObjectIdentifier _oid;        /// <summary>        /// Initializes a new instance of the <see cref="CipherDigitalSignature"/> class.        /// </summary>        /// <param name="oid">The object identifier.</param>        /// <param name="cipher">The cipher.</param>        public CipherDigitalSignature(ObjectIdentifier oid, AsymmetricCipher cipher)        {            if (cipher == null)                throw new ArgumentNullException("cipher");            this._cipher = cipher;            this._oid = oid;        }        /// <summary>        /// Verifies the signature.        /// </summary>        /// <param name="input">The input.</param>        /// <param name="signature">The signature.</param>        /// <returns></returns>        public override bool Verify(byte[] input, byte[] signature)        {            var sig = this._cipher.Decrypt(signature);            //  TODO:   Ensure that only 1 or 2 types are supported            var position = 1;            while (position < sig.Length && sig[position] != 0)                position++;            position++;            var sig1 = new byte[sig.Length - position];            Array.Copy(sig, position, sig1, 0, sig1.Length);            var hashData = this.Hash(input);            var expected = DerEncode(hashData);            if (expected.Length != sig1.Length)                return false;            for (int i = 0; i < expected.Length; i++)            {                if (expected[i] != sig1[i])                    return false;            }            return true;        }        /// <summary>        /// Creates the signature.        /// </summary>        /// <param name="input">The input.</param>        /// <returns></returns>        public override byte[] Sign(byte[] input)        {            //  Calculate hash value            var hashData = this.Hash(input);            //  Calculate DER string            var derEncodedHash = DerEncode(hashData);            //  Calculate signature            var rsaInputBlockSize = new byte[255];            rsaInputBlockSize[0] = 0x01;            for (int i = 1; i < rsaInputBlockSize.Length - derEncodedHash.Length - 1; i++)            {                rsaInputBlockSize[i] = 0xFF;            }            Array.Copy(derEncodedHash, 0, rsaInputBlockSize, rsaInputBlockSize.Length - derEncodedHash.Length, derEncodedHash.Length);            return this._cipher.Encrypt(rsaInputBlockSize).TrimLeadingZero().ToArray();        }        /// <summary>        /// Hashes the specified input.        /// </summary>        /// <param name="input">The input.</param>        /// <returns></returns>        protected abstract byte[] Hash(byte[] input);        /// <summary>        /// Encodes hash using DER.        /// </summary>        /// <param name="hashData">The hash data.</param>        /// <returns>DER Encoded byte array</returns>        protected byte[] DerEncode(byte[] hashData)        {            var data = new DerData();            var alg = new DerData();            alg.Write(this._oid);            alg.WriteNull();            data.Write(alg);            data.Write(hashData);            return data.Encode();        }    }}
 |