summary refs log tree commit diff
path: root/crypto/src/bcpg/ECPublicBCPGKey.cs
blob: 4733ee6c9fae467fca57df594717525a3ca5a10f (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
using System;
using System.IO;

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

namespace Org.BouncyCastle.Bcpg
{
    /// <remarks>Base class for an EC Public Key.</remarks>
    public abstract class ECPublicBcpgKey
        : BcpgObject, IBcpgKey
    {
        internal DerObjectIdentifier oid;
        internal BigInteger point;

        /// <param name="bcpgIn">The stream to read the packet from.</param>
        protected ECPublicBcpgKey(
            BcpgInputStream bcpgIn)
        {
            this.oid = DerObjectIdentifier.GetInstance(Asn1Object.FromByteArray(ReadBytesOfEncodedLength(bcpgIn)));
            this.point = new MPInteger(bcpgIn).Value;
        }

        protected ECPublicBcpgKey(
            DerObjectIdentifier oid,
            ECPoint point)
        {
            this.point = new BigInteger(1, point.GetEncoded(false));
            this.oid = oid;
        }

        protected ECPublicBcpgKey(
            DerObjectIdentifier oid,
            BigInteger encodedPoint)
        {
            this.point = encodedPoint;
            this.oid = oid;
        }

        /// <summary>The format, as a string, always "PGP".</summary>
        public string Format
        {
            get { return "PGP"; }
        }

        /// <summary>Return the standard PGP encoding of the key.</summary>
        public override byte[] GetEncoded()
        {
            try
            {
                return base.GetEncoded();
            }
            catch (IOException)
            {
                return null;
            }
        }

        public override void Encode(
            BcpgOutputStream bcpgOut)
        {
            byte[] oid = this.oid.GetEncoded();
            bcpgOut.Write(oid, 1, oid.Length - 1);

            MPInteger point = new MPInteger(this.point);
            bcpgOut.WriteObject(point);
        }

        public virtual BigInteger EncodedPoint
        {
            get { return point; }
        }

        public virtual DerObjectIdentifier CurveOid
        {
            get { return oid; }
        }

        protected static byte[] ReadBytesOfEncodedLength(
            BcpgInputStream bcpgIn)
        {
            int length = bcpgIn.ReadByte();
            if (length < 0)
                throw new EndOfStreamException();
            if (length == 0 || length == 0xFF)
                throw new IOException("future extensions not yet implemented");
            if (length > 127)
                throw new IOException("unsupported OID");

            byte[] buffer = new byte[length + 2];
            bcpgIn.ReadFully(buffer, 2, buffer.Length - 2);
            buffer[0] = (byte)0x06;
            buffer[1] = (byte)length;

            return buffer;
        }
    }
}