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

using Org.BouncyCastle.Math;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.IO;

namespace Org.BouncyCastle.Bcpg
{
	/// <remarks>Basic packet for a PGP public key.</remarks>
	public class PublicKeyEncSessionPacket
		: ContainedPacket //, PublicKeyAlgorithmTag
	{
		private int version;
		private long keyId;
		private PublicKeyAlgorithmTag algorithm;
        private byte[][] data;

		internal PublicKeyEncSessionPacket(
			BcpgInputStream bcpgIn)
		{
			version = bcpgIn.ReadByte();

			keyId |= (long)bcpgIn.ReadByte() << 56;
			keyId |= (long)bcpgIn.ReadByte() << 48;
			keyId |= (long)bcpgIn.ReadByte() << 40;
			keyId |= (long)bcpgIn.ReadByte() << 32;
			keyId |= (long)bcpgIn.ReadByte() << 24;
			keyId |= (long)bcpgIn.ReadByte() << 16;
			keyId |= (long)bcpgIn.ReadByte() << 8;
			keyId |= (uint)bcpgIn.ReadByte();

			algorithm = (PublicKeyAlgorithmTag) bcpgIn.ReadByte();

			switch ((PublicKeyAlgorithmTag) algorithm)
			{
				case PublicKeyAlgorithmTag.RsaEncrypt:
				case PublicKeyAlgorithmTag.RsaGeneral:
					data = new byte[][]{ new MPInteger(bcpgIn).GetEncoded() };
					break;
				case PublicKeyAlgorithmTag.ElGamalEncrypt:
				case PublicKeyAlgorithmTag.ElGamalGeneral:
                    MPInteger p = new MPInteger(bcpgIn);
                    MPInteger g = new MPInteger(bcpgIn);
					data = new byte[][]{
                        p.GetEncoded(),
                        g.GetEncoded(),
                    };
					break;
                case PublicKeyAlgorithmTag.ECDH:
                    data = new byte[][]{ Streams.ReadAll(bcpgIn) };
                    break;
				default:
					throw new IOException("unknown PGP public key algorithm encountered");
			}
		}

        public PublicKeyEncSessionPacket(
			long                    keyId,
			PublicKeyAlgorithmTag   algorithm,
			byte[][]                data)
		{
			this.version = 3;
			this.keyId = keyId;
			this.algorithm = algorithm;
            this.data = new byte[data.Length][];
            for (int i = 0; i < data.Length; ++i)
            {
                this.data[i] = Arrays.Clone(data[i]);
            }
		}

        public int Version
		{
			get { return version; }
		}

		public long KeyId
		{
			get { return keyId; }
		}

		public PublicKeyAlgorithmTag Algorithm
		{
			get { return algorithm; }
		}

        public byte[][] GetEncSessionKey()
		{
			return data;
		}

        public override void Encode(BcpgOutputStream bcpgOut)
		{
			MemoryStream bOut = new MemoryStream();
			using (var pOut = new BcpgOutputStream(bOut))
			{
				pOut.WriteByte((byte)version);
				pOut.WriteLong(keyId);
				pOut.WriteByte((byte)algorithm);

				for (int i = 0; i < data.Length; ++i)
				{
					pOut.Write(data[i]);
				}
			}

			bcpgOut.WritePacket(PacketTag.PublicKeyEncryptedSession, bOut.ToArray(), true);
		}
	}
}