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
|
using System;
using System.Diagnostics;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Pqc.Crypto.Ntru.Owcpa;
using Org.BouncyCastle.Pqc.Crypto.Ntru.ParameterSets;
namespace Org.BouncyCastle.Pqc.Crypto.Ntru
{
/// <summary>
/// NTRU secret encapsulation extractor.
/// </summary>
public class NtruKemExtractor : IEncapsulatedSecretExtractor
{
private readonly NtruParameters _parameters;
private readonly NtruPrivateKeyParameters _ntruPrivateKey;
public NtruKemExtractor(NtruPrivateKeyParameters ntruPrivateKey)
{
_parameters = ntruPrivateKey.Parameters;
_ntruPrivateKey = ntruPrivateKey;
}
public byte[] ExtractSecret(byte[] encapsulation)
{
Debug.Assert(_ntruPrivateKey != null);
NtruParameterSet parameterSet = _parameters.ParameterSet;
byte[] sk = _ntruPrivateKey.PrivateKey;
int i, fail;
byte[] rm;
byte[] buf = new byte[parameterSet.PrfKeyBytes + parameterSet.NtruCiphertextBytes()];
NtruOwcpa owcpa = new NtruOwcpa(parameterSet);
OwcpaDecryptResult owcpaResult = owcpa.Decrypt(encapsulation, _ntruPrivateKey.PrivateKey);
rm = owcpaResult.Rm;
fail = owcpaResult.Fail;
Sha3Digest sha3256 = new Sha3Digest(256);
byte[] k = new byte[sha3256.GetDigestSize()];
sha3256.BlockUpdate(rm, 0, rm.Length);
sha3256.DoFinal(k, 0);
/* shake(secret PRF key || input ciphertext) */
for (i = 0; i < parameterSet.PrfKeyBytes; i++)
{
buf[i] = sk[i + parameterSet.OwcpaSecretKeyBytes()];
}
for (i = 0; i < parameterSet.NtruCiphertextBytes(); i++)
{
buf[parameterSet.PrfKeyBytes + i] = encapsulation[i];
}
sha3256.Reset();
sha3256.BlockUpdate(buf, 0, buf.Length);
sha3256.DoFinal(rm, 0);
Cmov(k, rm, (byte)fail);
byte[] sharedKey = new byte[parameterSet.SharedKeyBytes];
Array.Copy(k, 0, sharedKey, 0, parameterSet.SharedKeyBytes);
Array.Clear(k, 0, k.Length);
return sharedKey;
}
private static void Cmov(byte[] r, byte[] x, byte b)
{
b = (byte)(~b + 1);
for (int i = 0; i < r.Length; i++)
{
r[i] ^= (byte)(b & (x[i] ^ r[i]));
}
}
public int EncapsulationLength => _parameters.ParameterSet.NtruCiphertextBytes();
}
}
|