| | | 1 | | using System; |
| | | 2 | | using Renci.SshNet.Common; |
| | | 3 | | |
| | | 4 | | namespace Renci.SshNet.Security.Cryptography |
| | | 5 | | { |
| | | 6 | | /// <summary> |
| | | 7 | | /// Implements digital signature where where asymmetric cipher is used. |
| | | 8 | | /// </summary> |
| | | 9 | | public abstract class CipherDigitalSignature : DigitalSignature |
| | | 10 | | { |
| | | 11 | | private readonly AsymmetricCipher _cipher; |
| | | 12 | | private readonly ObjectIdentifier _oid; |
| | | 13 | | |
| | | 14 | | /// <summary> |
| | | 15 | | /// Initializes a new instance of the <see cref="CipherDigitalSignature"/> class. |
| | | 16 | | /// </summary> |
| | | 17 | | /// <param name="oid">The object identifier.</param> |
| | | 18 | | /// <param name="cipher">The cipher.</param> |
| | 2768 | 19 | | protected CipherDigitalSignature(ObjectIdentifier oid, AsymmetricCipher cipher) |
| | 2768 | 20 | | { |
| | 2768 | 21 | | if (cipher is null) |
| | 0 | 22 | | { |
| | 0 | 23 | | throw new ArgumentNullException(nameof(cipher)); |
| | | 24 | | } |
| | | 25 | | |
| | 2768 | 26 | | _cipher = cipher; |
| | 2768 | 27 | | _oid = oid; |
| | 2768 | 28 | | } |
| | | 29 | | |
| | | 30 | | /// <summary> |
| | | 31 | | /// Verifies the signature. |
| | | 32 | | /// </summary> |
| | | 33 | | /// <param name="input">The input.</param> |
| | | 34 | | /// <param name="signature">The signature.</param> |
| | | 35 | | /// <returns> |
| | | 36 | | /// <see langword="true"/> if signature was successfully verified; otherwise <see langword="false"/>. |
| | | 37 | | /// </returns> |
| | | 38 | | public override bool Verify(byte[] input, byte[] signature) |
| | 1210 | 39 | | { |
| | 1210 | 40 | | var encryptedSignature = _cipher.Decrypt(signature); |
| | 1210 | 41 | | var hashData = Hash(input); |
| | 1210 | 42 | | var expected = DerEncode(hashData); |
| | 1210 | 43 | | return expected.IsEqualTo(encryptedSignature); |
| | 1210 | 44 | | } |
| | | 45 | | |
| | | 46 | | /// <summary> |
| | | 47 | | /// Creates the signature. |
| | | 48 | | /// </summary> |
| | | 49 | | /// <param name="input">The input.</param> |
| | | 50 | | /// <returns> |
| | | 51 | | /// Signed input data. |
| | | 52 | | /// </returns> |
| | | 53 | | public override byte[] Sign(byte[] input) |
| | 696 | 54 | | { |
| | | 55 | | // Calculate hash value |
| | 696 | 56 | | var hashData = Hash(input); |
| | | 57 | | |
| | | 58 | | // Calculate DER string |
| | 696 | 59 | | var derEncodedHash = DerEncode(hashData); |
| | | 60 | | |
| | 696 | 61 | | return _cipher.Encrypt(derEncodedHash).TrimLeadingZeros(); |
| | 696 | 62 | | } |
| | | 63 | | |
| | | 64 | | /// <summary> |
| | | 65 | | /// Hashes the specified input. |
| | | 66 | | /// </summary> |
| | | 67 | | /// <param name="input">The input.</param> |
| | | 68 | | /// <returns>Hashed data.</returns> |
| | | 69 | | protected abstract byte[] Hash(byte[] input); |
| | | 70 | | |
| | | 71 | | /// <summary> |
| | | 72 | | /// Encodes hash using DER. |
| | | 73 | | /// </summary> |
| | | 74 | | /// <param name="hashData">The hash data.</param> |
| | | 75 | | /// <returns> |
| | | 76 | | /// DER Encoded byte array. |
| | | 77 | | /// </returns> |
| | | 78 | | protected byte[] DerEncode(byte[] hashData) |
| | 1906 | 79 | | { |
| | 1906 | 80 | | var alg = new DerData(); |
| | 1906 | 81 | | alg.Write(_oid); |
| | 1906 | 82 | | alg.WriteNull(); |
| | | 83 | | |
| | 1906 | 84 | | var data = new DerData(); |
| | 1906 | 85 | | data.Write(alg); |
| | 1906 | 86 | | data.Write(hashData); |
| | 1906 | 87 | | return data.Encode(); |
| | 1906 | 88 | | } |
| | | 89 | | } |
| | | 90 | | } |