summary refs log tree commit diff
path: root/crypto/src/bcpg/ECDHPublicBCPGKey.cs
blob: e43100d3ab5aa77dcbe8b1453783d82186fe9ffe (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
using System;

using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;

namespace Org.BouncyCastle.Bcpg
{
    /// <remarks>Base class for an ECDH Public Key.</remarks>
    public class ECDHPublicBcpgKey
        : ECPublicBcpgKey
    {
        private byte reserved;
        private HashAlgorithmTag hashFunctionId;
        private SymmetricKeyAlgorithmTag symAlgorithmId;

        /// <param name="bcpgIn">The stream to read the packet from.</param>
        public ECDHPublicBcpgKey(BcpgInputStream bcpgIn)
            : base(bcpgIn)
        {
            int length = bcpgIn.ReadByte();
            if (length != 3)
                throw new InvalidOperationException("KDF parameters size of 3 expected.");

#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
            Span<byte> kdfParameters = stackalloc byte[3];
#else
            byte[] kdfParameters = new byte[3];
#endif
            bcpgIn.ReadFully(kdfParameters);

            reserved = kdfParameters[0];
            hashFunctionId = (HashAlgorithmTag)kdfParameters[1];
            symAlgorithmId = (SymmetricKeyAlgorithmTag)kdfParameters[2];

            VerifyHashAlgorithm();
            VerifySymmetricKeyAlgorithm();
        }

        public ECDHPublicBcpgKey(
            DerObjectIdentifier oid,
            ECPoint point,
            HashAlgorithmTag hashAlgorithm,
            SymmetricKeyAlgorithmTag symmetricKeyAlgorithm)
            : base(oid, point)
        {
            reserved = 1;
            hashFunctionId = hashAlgorithm;
            symAlgorithmId = symmetricKeyAlgorithm;

            VerifyHashAlgorithm();
            VerifySymmetricKeyAlgorithm();
        }

        public ECDHPublicBcpgKey(
            DerObjectIdentifier oid,
            BigInteger point,
            HashAlgorithmTag hashAlgorithm,
            SymmetricKeyAlgorithmTag symmetricKeyAlgorithm)
            : base(oid, point)
        {
            reserved = 1;
            hashFunctionId = hashAlgorithm;
            symAlgorithmId = symmetricKeyAlgorithm;

            VerifyHashAlgorithm();
            VerifySymmetricKeyAlgorithm();
        }

        public virtual byte Reserved
        {
            get { return reserved; }
        }

        public virtual HashAlgorithmTag HashAlgorithm
        {
            get { return hashFunctionId; }
        }

        public virtual SymmetricKeyAlgorithmTag SymmetricKeyAlgorithm
        {
            get { return symAlgorithmId; }
        }

        public override void Encode(
            BcpgOutputStream bcpgOut)
        {
            base.Encode(bcpgOut);
            bcpgOut.WriteByte(0x3);
            bcpgOut.WriteByte(reserved);
            bcpgOut.WriteByte((byte)hashFunctionId);
            bcpgOut.WriteByte((byte)symAlgorithmId);
        }

        private void VerifyHashAlgorithm()
        {
            switch (hashFunctionId)
            {
            case HashAlgorithmTag.Sha256:
            case HashAlgorithmTag.Sha384:
            case HashAlgorithmTag.Sha512:
                break;
            default:
                throw new InvalidOperationException("Hash algorithm must be SHA-256 or stronger.");
            }
        }

        private void VerifySymmetricKeyAlgorithm()
        {
            switch (symAlgorithmId)
            {
            case SymmetricKeyAlgorithmTag.Aes128:
            case SymmetricKeyAlgorithmTag.Aes192:
            case SymmetricKeyAlgorithmTag.Aes256:
                break;
            default:
                throw new InvalidOperationException("Symmetric key algorithm must be AES-128 or stronger.");
            }
        }
    }
}