summary refs log tree commit diff
path: root/crypto/src/pqc/crypto/ntru/NtruKemGenerator.cs
blob: 283bddbda21e3beaa05c043704da9fbcfa30fb8a (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
using System;

using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Pqc.Crypto.Ntru.Owcpa;
using Org.BouncyCastle.Pqc.Crypto.Ntru.Polynomials;
using Org.BouncyCastle.Security;

namespace Org.BouncyCastle.Pqc.Crypto.Ntru
{
    /// <summary>
    /// Encapsulate a secret using NTRU. Returns an <see cref="NtruEncapsulation"/> as encapsulation.
    /// </summary>
    ///
    /// <seealso cref="NtruKemExtractor"/>
    /// <seealso href="https://ntru.org/">NTRU website</seealso>
    public class NtruKemGenerator : IEncapsulatedSecretGenerator
    {
        private readonly SecureRandom _random;

        public NtruKemGenerator(SecureRandom random)
        {
            _random = random;
        }

        public ISecretWithEncapsulation GenerateEncapsulated(AsymmetricKeyParameter recipientKey)
        {
            var parameterSet = ((NtruPublicKeyParameters)recipientKey).GetParameters().ParameterSet;
            var sampling = new NtruSampling(parameterSet);
            var owcpa = new NtruOwcpa(parameterSet);
            Polynomial r;
            Polynomial m;
            var rm = new byte[parameterSet.OwcpaMsgBytes()];
            var rmSeed = new byte[parameterSet.SampleRmBytes()];

            _random.NextBytes(rmSeed);

            var pair = sampling.SampleRm(rmSeed);
            r = pair.R();
            m = pair.M();

            var rm1 = r.S3ToBytes(parameterSet.OwcpaMsgBytes());
            Array.Copy(rm1, 0, rm, 0, rm1.Length);

            var rm2 = m.S3ToBytes(rm.Length - parameterSet.PackTrinaryBytes());

            Array.Copy(rm2, 0, rm, parameterSet.PackTrinaryBytes(), rm2.Length);

            var sha3256 = new Sha3Digest(256);
            sha3256.BlockUpdate(rm, 0, rm.Length);


            var k = new byte[sha3256.GetDigestSize()];

            sha3256.DoFinal(k, 0);


            r.Z3ToZq();

            var c = owcpa.Encrypt(r, m, ((NtruPublicKeyParameters)recipientKey).PublicKey);

            var sharedKey = new byte[parameterSet.SharedKeyBytes];
            Array.Copy(k, 0, sharedKey, 0, sharedKey.Length);

            Array.Clear(k, 0, k.Length);

            return new NtruEncapsulation(sharedKey, c);
        }
    }
}