Skip to content

Commit ae9ac87

Browse files
committed
Refactoring in NTRU
1 parent 0f3e412 commit ae9ac87

9 files changed

+173
-131
lines changed
+19-34
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,56 @@
11
using System;
2-
using System.Diagnostics;
32

43
using Org.BouncyCastle.Crypto;
54
using Org.BouncyCastle.Crypto.Digests;
65
using Org.BouncyCastle.Pqc.Crypto.Ntru.Owcpa;
7-
using Org.BouncyCastle.Pqc.Crypto.Ntru.ParameterSets;
6+
using Org.BouncyCastle.Utilities;
87

98
namespace Org.BouncyCastle.Pqc.Crypto.Ntru
109
{
1110
/// <summary>
1211
/// NTRU secret encapsulation extractor.
1312
/// </summary>
14-
public class NtruKemExtractor : IEncapsulatedSecretExtractor
13+
public class NtruKemExtractor
14+
: IEncapsulatedSecretExtractor
1515
{
16-
private readonly NtruParameters _parameters;
17-
private readonly NtruPrivateKeyParameters _ntruPrivateKey;
16+
private readonly NtruPrivateKeyParameters m_privateKey;
1817

1918
public NtruKemExtractor(NtruPrivateKeyParameters ntruPrivateKey)
2019
{
21-
_parameters = ntruPrivateKey.Parameters;
22-
_ntruPrivateKey = ntruPrivateKey;
20+
m_privateKey = ntruPrivateKey ?? throw new ArgumentNullException(nameof(ntruPrivateKey));
2321
}
2422

25-
2623
public byte[] ExtractSecret(byte[] encapsulation)
2724
{
28-
Debug.Assert(_ntruPrivateKey != null);
25+
var parameterSet = m_privateKey.Parameters.ParameterSet;
2926

30-
NtruParameterSet parameterSet = _parameters.ParameterSet;
27+
if (encapsulation == null)
28+
throw new ArgumentNullException(nameof(encapsulation));
29+
if (encapsulation.Length != parameterSet.NtruCiphertextBytes())
30+
throw new ArgumentException(nameof(encapsulation));
3131

32-
byte[] sk = _ntruPrivateKey.PrivateKey;
33-
int i, fail;
34-
byte[] rm;
35-
byte[] buf = new byte[parameterSet.PrfKeyBytes + parameterSet.NtruCiphertextBytes()];
32+
// TODO[pqc] Avoid copy?
33+
byte[] sk = m_privateKey.GetEncoded();
3634

3735
NtruOwcpa owcpa = new NtruOwcpa(parameterSet);
38-
OwcpaDecryptResult owcpaResult = owcpa.Decrypt(encapsulation, _ntruPrivateKey.PrivateKey);
39-
rm = owcpaResult.Rm;
40-
fail = owcpaResult.Fail;
36+
OwcpaDecryptResult owcpaResult = owcpa.Decrypt(encapsulation, sk);
37+
byte[] rm = owcpaResult.Rm;
38+
int fail = owcpaResult.Fail;
4139

4240
Sha3Digest sha3256 = new Sha3Digest(256);
43-
4441
byte[] k = new byte[sha3256.GetDigestSize()];
4542

4643
sha3256.BlockUpdate(rm, 0, rm.Length);
4744
sha3256.DoFinal(k, 0);
4845

4946
/* shake(secret PRF key || input ciphertext) */
50-
for (i = 0; i < parameterSet.PrfKeyBytes; i++)
51-
{
52-
buf[i] = sk[i + parameterSet.OwcpaSecretKeyBytes()];
53-
}
54-
55-
for (i = 0; i < parameterSet.NtruCiphertextBytes(); i++)
56-
{
57-
buf[parameterSet.PrfKeyBytes + i] = encapsulation[i];
58-
}
59-
60-
sha3256.Reset();
61-
sha3256.BlockUpdate(buf, 0, buf.Length);
47+
sha3256.BlockUpdate(sk, parameterSet.OwcpaSecretKeyBytes(), parameterSet.PrfKeyBytes);
48+
sha3256.BlockUpdate(encapsulation, 0, encapsulation.Length);
6249
sha3256.DoFinal(rm, 0);
6350

6451
Cmov(k, rm, (byte)fail);
6552

66-
byte[] sharedKey = new byte[parameterSet.SharedKeyBytes];
67-
Array.Copy(k, 0, sharedKey, 0, parameterSet.SharedKeyBytes);
68-
53+
var sharedKey = Arrays.CopyOfRange(k, 0, parameterSet.SharedKeyBytes);
6954
Array.Clear(k, 0, k.Length);
7055

7156
return sharedKey;
@@ -80,6 +65,6 @@ private static void Cmov(byte[] r, byte[] x, byte b)
8065
}
8166
}
8267

83-
public int EncapsulationLength => _parameters.ParameterSet.NtruCiphertextBytes();
68+
public int EncapsulationLength => m_privateKey.Parameters.ParameterSet.NtruCiphertextBytes();
8469
}
8570
}

crypto/src/pqc/crypto/ntru/NtruKemGenerator.cs

+17-14
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Org.BouncyCastle.Pqc.Crypto.Ntru.Owcpa;
66
using Org.BouncyCastle.Pqc.Crypto.Ntru.Polynomials;
77
using Org.BouncyCastle.Security;
8+
using Org.BouncyCastle.Utilities;
89

910
namespace Org.BouncyCastle.Pqc.Crypto.Ntru
1011
{
@@ -14,24 +15,30 @@ namespace Org.BouncyCastle.Pqc.Crypto.Ntru
1415
///
1516
/// <seealso cref="NtruKemExtractor"/>
1617
/// <seealso href="https://ntru.org/">NTRU website</seealso>
17-
public class NtruKemGenerator : IEncapsulatedSecretGenerator
18+
public class NtruKemGenerator
19+
: IEncapsulatedSecretGenerator
1820
{
19-
private readonly SecureRandom _random;
21+
private readonly SecureRandom m_random;
2022

2123
public NtruKemGenerator(SecureRandom random)
2224
{
23-
_random = random;
25+
m_random = random ?? throw new ArgumentNullException(nameof(random));
2426
}
2527

2628
public ISecretWithEncapsulation GenerateEncapsulated(AsymmetricKeyParameter recipientKey)
2729
{
28-
var parameterSet = ((NtruPublicKeyParameters)recipientKey).Parameters.ParameterSet;
30+
if (recipientKey == null)
31+
throw new ArgumentNullException(nameof(recipientKey));
32+
if (!(recipientKey is NtruPublicKeyParameters publicKey))
33+
throw new ArgumentException(nameof(recipientKey));
34+
35+
var parameterSet = publicKey.Parameters.ParameterSet;
2936
var sampling = new NtruSampling(parameterSet);
3037
var owcpa = new NtruOwcpa(parameterSet);
3138
var rm = new byte[parameterSet.OwcpaMsgBytes()];
3239
var rmSeed = new byte[parameterSet.SampleRmBytes()];
3340

34-
_random.NextBytes(rmSeed);
41+
m_random.NextBytes(rmSeed);
3542

3643
var pair = sampling.SampleRm(rmSeed);
3744
Polynomial r = pair.R();
@@ -41,24 +48,20 @@ public ISecretWithEncapsulation GenerateEncapsulated(AsymmetricKeyParameter reci
4148
m.S3ToBytes(rm, parameterSet.PackTrinaryBytes());
4249

4350
var sha3256 = new Sha3Digest(256);
44-
sha3256.BlockUpdate(rm, 0, rm.Length);
45-
46-
4751
var k = new byte[sha3256.GetDigestSize()];
4852

53+
sha3256.BlockUpdate(rm, 0, rm.Length);
4954
sha3256.DoFinal(k, 0);
5055

51-
5256
r.Z3ToZq();
5357

54-
var c = owcpa.Encrypt(r, m, ((NtruPublicKeyParameters)recipientKey).PublicKey);
55-
56-
var sharedKey = new byte[parameterSet.SharedKeyBytes];
57-
Array.Copy(k, 0, sharedKey, 0, sharedKey.Length);
58+
// TODO[pqc] Avoid copy?
59+
var c = owcpa.Encrypt(r, m, publicKey.GetEncoded());
5860

61+
var sharedKey = Arrays.CopyOfRange(k, 0, parameterSet.SharedKeyBytes);
5962
Array.Clear(k, 0, k.Length);
6063

6164
return new NtruEncapsulation(sharedKey, c);
6265
}
6366
}
64-
}
67+
}

crypto/src/pqc/crypto/ntru/NtruKeyPairGenerator.cs

+23-21
Original file line numberDiff line numberDiff line change
@@ -2,44 +2,46 @@
22

33
using Org.BouncyCastle.Crypto;
44
using Org.BouncyCastle.Pqc.Crypto.Ntru.Owcpa;
5-
using Org.BouncyCastle.Pqc.Crypto.Ntru.ParameterSets;
65
using Org.BouncyCastle.Security;
6+
using Org.BouncyCastle.Utilities;
77

88
namespace Org.BouncyCastle.Pqc.Crypto.Ntru
99
{
10-
public class NtruKeyPairGenerator : IAsymmetricCipherKeyPairGenerator
10+
public class NtruKeyPairGenerator
11+
: IAsymmetricCipherKeyPairGenerator
1112
{
12-
private NtruKeyGenerationParameters _keygenParameters;
13-
private SecureRandom _random;
13+
private NtruKeyGenerationParameters m_keyGenParameters;
14+
private SecureRandom m_random;
1415

1516
public void Init(KeyGenerationParameters parameters)
1617
{
17-
_keygenParameters = (NtruKeyGenerationParameters)parameters;
18-
_random = parameters.Random;
18+
if (parameters == null)
19+
throw new ArgumentNullException(nameof(parameters));
20+
21+
m_keyGenParameters = (NtruKeyGenerationParameters)parameters;
22+
m_random = parameters.Random;
1923
}
2024

2125
public AsymmetricCipherKeyPair GenerateKeyPair()
2226
{
23-
// Debug.Assert(this._random != null);
24-
NtruParameterSet parameterSet = _keygenParameters.NtruParameters.ParameterSet;
27+
var parameters = m_keyGenParameters.NtruParameters;
28+
var parameterSet = parameters.ParameterSet;
2529

26-
var seed = new byte[parameterSet.SampleFgBytes()];
27-
_random.NextBytes(seed);
30+
var seed = SecureRandom.GetNextBytes(m_random, parameterSet.SampleFgBytes());
2831

2932
NtruOwcpa owcpa = new NtruOwcpa(parameterSet);
3033
OwcpaKeyPair owcpaKeys = owcpa.KeyPair(seed);
3134

3235
byte[] publicKey = owcpaKeys.PublicKey;
33-
byte[] privateKey = new byte[parameterSet.NtruSecretKeyBytes()];
34-
byte[] owcpaPrivateKey = owcpaKeys.PrivateKey;
35-
Array.Copy(owcpaPrivateKey, 0, privateKey, 0, owcpaPrivateKey.Length);
36-
//
37-
byte[] prfBytes = new byte[parameterSet.PrfKeyBytes];
38-
_random.NextBytes(prfBytes);
39-
Array.Copy(prfBytes, 0, privateKey, parameterSet.OwcpaSecretKeyBytes(), prfBytes.Length);
40-
41-
return new AsymmetricCipherKeyPair(new NtruPublicKeyParameters(_keygenParameters.NtruParameters, publicKey),
42-
new NtruPrivateKeyParameters(_keygenParameters.NtruParameters, privateKey));
36+
37+
byte[] privateKey = Arrays.CopyOf(owcpaKeys.PrivateKey, parameterSet.NtruSecretKeyBytes());
38+
m_random.NextBytes(privateKey, parameterSet.OwcpaSecretKeyBytes(), parameterSet.PrfKeyBytes);
39+
40+
#pragma warning disable CS0618 // Type or member is obsolete
41+
return new AsymmetricCipherKeyPair(
42+
new NtruPublicKeyParameters(parameters, publicKey),
43+
new NtruPrivateKeyParameters(parameters, privateKey));
44+
#pragma warning restore CS0618 // Type or member is obsolete
4345
}
4446
}
45-
}
47+
}

crypto/src/pqc/crypto/ntru/NtruParameters.cs

+13-10
Original file line numberDiff line numberDiff line change
@@ -42,21 +42,24 @@ public static readonly NtruParameters NtruHps40961229
4242
/// </summary>
4343
public static readonly NtruParameters NtruHrss1373 = new NtruParameters("ntruhrss1373", new NtruHrss1373());
4444

45-
/// <summary>
46-
/// Currently selected parameter set
47-
/// </summary>
48-
internal readonly NtruParameterSet ParameterSet;
49-
50-
private readonly string _name;
45+
private readonly string m_name;
46+
private readonly NtruParameterSet m_parameterSet;
5147

5248
private NtruParameters(string name, NtruParameterSet parameterSet)
5349
{
54-
_name = name;
55-
ParameterSet = parameterSet;
50+
m_name = name;
51+
m_parameterSet = parameterSet;
5652
}
5753

58-
public string Name => _name;
54+
public string Name => m_name;
55+
56+
internal NtruParameterSet ParameterSet => m_parameterSet;
57+
58+
internal int PrivateKeyLength => ParameterSet.NtruSecretKeyBytes();
59+
60+
internal int PublicKeyLength => ParameterSet.NtruPublicKeyBytes();
5961

62+
// TODO[pqc] bc-java uses 'SessionKeySize' for this
6063
public int DefaultKeySize => ParameterSet.SharedKeyBytes * 8;
6164
}
62-
}
65+
}
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,40 @@
1-
namespace Org.BouncyCastle.Pqc.Crypto.Ntru
1+
using System;
2+
3+
namespace Org.BouncyCastle.Pqc.Crypto.Ntru
24
{
35
public sealed class NtruPrivateKeyParameters
46
: NtruKeyParameters
57
{
6-
private byte[] _privateKey;
7-
8-
public byte[] PrivateKey
8+
public static NtruPrivateKeyParameters FromEncoding(NtruParameters parameters, byte[] encoding)
99
{
10-
get => (byte[])_privateKey.Clone();
11-
private set => _privateKey = (byte[])value.Clone();
10+
#pragma warning disable CS0618 // Type or member is obsolete
11+
return new NtruPrivateKeyParameters(parameters, encoding);
12+
#pragma warning restore CS0618 // Type or member is obsolete
1213
}
1314

14-
public NtruPrivateKeyParameters(NtruParameters parameters, byte[] key) : base(true, parameters)
15+
private readonly byte[] m_privateKey;
16+
17+
[Obsolete("Use 'FromEncoding' instead")]
18+
public NtruPrivateKeyParameters(NtruParameters parameters, byte[] key)
19+
: base(privateKey: true, parameters)
1520
{
16-
PrivateKey = key;
21+
if (parameters == null)
22+
throw new ArgumentNullException(nameof(parameters));
23+
if (key == null)
24+
throw new ArgumentNullException(nameof(key));
25+
if (key.Length != parameters.PrivateKeyLength)
26+
throw new ArgumentException("invalid encoding", nameof(key));
27+
28+
m_privateKey = (byte[])key.Clone();
1729
}
1830

19-
public override byte[] GetEncoded()
31+
public override byte[] GetEncoded() => (byte[])m_privateKey.Clone();
32+
33+
[Obsolete("Use 'GetEncoded' instead")]
34+
public byte[] PrivateKey
2035
{
21-
return PrivateKey;
36+
get => GetEncoded();
37+
private set => throw new NotSupportedException();
2238
}
2339
}
24-
}
40+
}
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,40 @@
1-
namespace Org.BouncyCastle.Pqc.Crypto.Ntru
1+
using System;
2+
3+
namespace Org.BouncyCastle.Pqc.Crypto.Ntru
24
{
35
public sealed class NtruPublicKeyParameters
46
: NtruKeyParameters
57
{
6-
private byte[] _publicKey;
7-
8-
public byte[] PublicKey
8+
public static NtruPublicKeyParameters FromEncoding(NtruParameters parameters, byte[] encoding)
99
{
10-
get => (byte[])_publicKey.Clone();
11-
set => _publicKey = (byte[])value.Clone();
10+
#pragma warning disable CS0618 // Type or member is obsolete
11+
return new NtruPublicKeyParameters(parameters, encoding);
12+
#pragma warning restore CS0618 // Type or member is obsolete
1213
}
1314

14-
public NtruPublicKeyParameters(NtruParameters parameters, byte[] key) : base(false, parameters)
15+
private readonly byte[] m_publicKey;
16+
17+
[Obsolete("Use 'FromEncoding' instead")]
18+
public NtruPublicKeyParameters(NtruParameters parameters, byte[] key)
19+
: base(privateKey: false, parameters)
1520
{
16-
PublicKey = key;
21+
if (parameters == null)
22+
throw new ArgumentNullException(nameof(parameters));
23+
if (key == null)
24+
throw new ArgumentNullException(nameof(key));
25+
if (key.Length != parameters.PublicKeyLength)
26+
throw new ArgumentException("invalid encoding", nameof(key));
27+
28+
m_publicKey = (byte[])key.Clone();
1729
}
1830

19-
public override byte[] GetEncoded()
31+
public override byte[] GetEncoded() => (byte[])m_publicKey.Clone();
32+
33+
[Obsolete("Use 'GetEncoded' instead")]
34+
public byte[] PublicKey
2035
{
21-
return PublicKey;
36+
get => GetEncoded();
37+
set => throw new NotSupportedException();
2238
}
2339
}
24-
}
40+
}

0 commit comments

Comments
 (0)