summary refs log tree commit diff
path: root/crypto/src/crypto/generators/GOST3410KeyPairGenerator.cs
blob: 5878da64be551e139d7f0c5648e76e7d22c390b7 (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
using System;

using Org.BouncyCastle.Asn1.CryptoPro;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;

namespace Org.BouncyCastle.Crypto.Generators
{
	/**
	 * a GOST3410 key pair generator.
	 * This generates GOST3410 keys in line with the method described
	 * in GOST R 34.10-94.
	 */
	public class Gost3410KeyPairGenerator
		: IAsymmetricCipherKeyPairGenerator
	{
		private Gost3410KeyGenerationParameters param;

		public void Init(
			KeyGenerationParameters parameters)
		{
			if (parameters is Gost3410KeyGenerationParameters)
			{
				this.param = (Gost3410KeyGenerationParameters) parameters;
			}
			else
			{
				Gost3410KeyGenerationParameters kgp = new Gost3410KeyGenerationParameters(
					parameters.Random,
					CryptoProObjectIdentifiers.GostR3410x94CryptoProA);

				if (parameters.Strength != kgp.Parameters.P.BitLength - 1)
				{
					// TODO Should we complain?
				}

				this.param = kgp;
			}
		}

		public AsymmetricCipherKeyPair GenerateKeyPair()
		{
			SecureRandom random = param.Random;
			Gost3410Parameters gost3410Params = param.Parameters;

			BigInteger q = gost3410Params.Q;
			BigInteger x;
			do
			{
				x = new BigInteger(256, random);
			}
			while (x.SignValue < 1 || x.CompareTo(q) >= 0);

			BigInteger p = gost3410Params.P;
			BigInteger a = gost3410Params.A;

			// calculate the public key.
			BigInteger y = a.ModPow(x, p);

			if (param.PublicKeyParamSet != null)
			{
				return new AsymmetricCipherKeyPair(
					new Gost3410PublicKeyParameters(y, param.PublicKeyParamSet),
					new Gost3410PrivateKeyParameters(x, param.PublicKeyParamSet));
			}

			return new AsymmetricCipherKeyPair(
				new Gost3410PublicKeyParameters(y, gost3410Params),
				new Gost3410PrivateKeyParameters(x, gost3410Params));
		}
	}
}