diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj
index a80ac39ea..e2ad3ea69 100644
--- a/crypto/crypto.csproj
+++ b/crypto/crypto.csproj
@@ -1714,6 +1714,11 @@
BuildAction = "Compile"
/>
<File
+ RelPath = "src\asn1\rosstandart\RosstandartObjectIdentifiers.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
RelPath = "src\asn1\sec\ECPrivateKeyStructure.cs"
SubType = "Code"
BuildAction = "Compile"
@@ -3234,6 +3239,11 @@
BuildAction = "Compile"
/>
<File
+ RelPath = "src\crypto\agreement\SM2KeyExchange.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
RelPath = "src\crypto\agreement\jpake\JPakeParticipant.cs"
SubType = "Code"
BuildAction = "Compile"
@@ -3269,6 +3279,11 @@
BuildAction = "Compile"
/>
<File
+ RelPath = "src\crypto\agreement\kdf\ConcatenationKdfGenerator.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
RelPath = "src\crypto\agreement\kdf\DHKdfParameters.cs"
SubType = "Code"
BuildAction = "Compile"
@@ -3714,6 +3729,11 @@
BuildAction = "Compile"
/>
<File
+ RelPath = "src\crypto\engines\SM2Engine.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
RelPath = "src\crypto\engines\TEAEngine.cs"
SubType = "Code"
BuildAction = "Compile"
@@ -4369,6 +4389,11 @@
BuildAction = "Compile"
/>
<File
+ RelPath = "src\crypto\parameters\ParametersWithID.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
RelPath = "src\crypto\parameters\ParametersWithIV.cs"
SubType = "Code"
BuildAction = "Compile"
@@ -4424,6 +4449,16 @@
BuildAction = "Compile"
/>
<File
+ RelPath = "src\crypto\parameters\SM2KeyExchangePrivateParameters.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "src\crypto\parameters\SM2KeyExchangePublicParameters.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
RelPath = "src\crypto\parameters\Srp6GroupParameters.cs"
SubType = "Code"
BuildAction = "Compile"
@@ -4614,6 +4649,11 @@
BuildAction = "Compile"
/>
<File
+ RelPath = "src\crypto\signers\SM2Signer.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
RelPath = "src\crypto\signers\X931Signer.cs"
SubType = "Code"
BuildAction = "Compile"
@@ -7489,6 +7529,38 @@
BuildAction = "Compile"
/>
<File
+ RelPath = "test\data\cert_chain.data"
+ BuildAction = "EmbeddedResource"
+ />
+ <File
+ RelPath = "test\data\cert_chain_nl.data"
+ BuildAction = "EmbeddedResource"
+ />
+ <File
+ RelPath = "test\data\qvRooCa3.crt"
+ BuildAction = "EmbeddedResource"
+ />
+ <File
+ RelPath = "test\data\suvaEE.crt"
+ BuildAction = "EmbeddedResource"
+ />
+ <File
+ RelPath = "test\data\suvaEmail1.crt"
+ BuildAction = "EmbeddedResource"
+ />
+ <File
+ RelPath = "test\data\suvaRoot1.crt"
+ BuildAction = "EmbeddedResource"
+ />
+ <File
+ RelPath = "test\data\ThawteSGCCA.cer"
+ BuildAction = "EmbeddedResource"
+ />
+ <File
+ RelPath = "test\data\ThawteSGCCA.crl"
+ BuildAction = "EmbeddedResource"
+ />
+ <File
RelPath = "test\data\asn1\masterlist-content.data"
BuildAction = "EmbeddedResource"
/>
@@ -7525,6 +7597,14 @@
BuildAction = "EmbeddedResource"
/>
<File
+ RelPath = "test\data\cms\sigs\rawsha256nonull.p7m"
+ BuildAction = "EmbeddedResource"
+ />
+ <File
+ RelPath = "test\data\cms\sigs\SignedMSPkcs7.sig"
+ BuildAction = "EmbeddedResource"
+ />
+ <File
RelPath = "test\data\crypto\SHA3TestVectors.txt"
BuildAction = "EmbeddedResource"
/>
@@ -11910,6 +11990,21 @@
BuildAction = "Compile"
/>
<File
+ RelPath = "test\src\crypto\test\SM2EngineTest.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "test\src\crypto\test\SM2KeyExchangeTest.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "test\src\crypto\test\SM2SignerTest.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
RelPath = "test\src\crypto\test\SM3DigestTest.cs"
SubType = "Code"
BuildAction = "Compile"
@@ -12795,6 +12890,11 @@
BuildAction = "Compile"
/>
<File
+ RelPath = "test\src\util\test\TestRandomBigInteger.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
RelPath = "test\src\util\test\UncloseableStream.cs"
SubType = "Code"
BuildAction = "Compile"
diff --git a/crypto/src/asn1/cryptopro/ECGOST3410NamedCurves.cs b/crypto/src/asn1/cryptopro/ECGOST3410NamedCurves.cs
index 32d3103af..9c366503d 100644
--- a/crypto/src/asn1/cryptopro/ECGOST3410NamedCurves.cs
+++ b/crypto/src/asn1/cryptopro/ECGOST3410NamedCurves.cs
@@ -1,7 +1,7 @@
using System;
using System.Collections;
-using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Rosstandart;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
@@ -10,9 +10,9 @@ using Org.BouncyCastle.Utilities.Collections;
namespace Org.BouncyCastle.Asn1.CryptoPro
{
- /**
- * table of the available named parameters for GOST 3410-2001.
- */
+ /// <summary>
+ /// Table of the available named parameters for GOST 3410-2001 / 2012.
+ /// </summary>
public sealed class ECGost3410NamedCurves
{
private ECGost3410NamedCurves()
@@ -119,17 +119,98 @@ namespace Org.BouncyCastle.Asn1.CryptoPro
parameters[CryptoProObjectIdentifiers.GostR3410x2001CryptoProC] = ecParams;
+ //GOST34.10 2012
+ mod_p = new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639319"); //p
+ mod_q = new BigInteger("115792089237316195423570985008687907853073762908499243225378155805079068850323"); //q
+ curve = new FpCurve(
+ mod_p, // p
+ new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639316"), // a
+ new BigInteger("166"), // b
+ mod_q,
+ BigInteger.One);
+
+ ecParams = new ECDomainParameters(
+ curve,
+ curve.CreatePoint(
+ new BigInteger("1"), // x
+ new BigInteger("64033881142927202683649881450433473985931760268884941288852745803908878638612")), // y
+ mod_q); // q
+
+ parameters[RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256_paramSetA] = ecParams;
+
+ mod_p = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7",16); //p
+ mod_q = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27E69532F48D89116FF22B8D4E0560609B4B38ABFAD2B85DCACDB1411F10B275",16); //q
+ curve = new FpCurve(
+ mod_p, // p
+ new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC4",16), // a
+ new BigInteger("E8C2505DEDFC86DDC1BD0B2B6667F1DA34B82574761CB0E879BD081CFD0B6265EE3CB090F30D27614CB4574010DA90DD862EF9D4EBEE4761503190785A71C760",16), // b
+ mod_q,
+ BigInteger.One);
+
+ ecParams = new ECDomainParameters(
+ curve,
+ curve.CreatePoint(
+ new BigInteger("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003"), // x
+ new BigInteger("7503CFE87A836AE3A61B8816E25450E6CE5E1C93ACF1ABC1778064FDCBEFA921DF1626BE4FD036E93D75E6A50E3A41E98028FE5FC235F5B889A589CB5215F2A4",16)), // y
+ mod_q); // q
+
+ parameters[RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetA] = ecParams;
+
+ mod_p = new BigInteger("8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006F",16); //p
+ mod_q = new BigInteger("800000000000000000000000000000000000000000000000000000000000000149A1EC142565A545ACFDB77BD9D40CFA8B996712101BEA0EC6346C54374F25BD",16); //q
+ curve = new FpCurve(
+ mod_p, // p
+ new BigInteger("8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006C",16), // a
+ new BigInteger("687D1B459DC841457E3E06CF6F5E2517B97C7D614AF138BCBF85DC806C4B289F3E965D2DB1416D217F8B276FAD1AB69C50F78BEE1FA3106EFB8CCBC7C5140116",16), // b
+ mod_q,
+ BigInteger.One);
+
+ ecParams = new ECDomainParameters(
+ curve,
+ curve.CreatePoint(
+ new BigInteger("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002"), // x
+ new BigInteger("1A8F7EDA389B094C2C071E3647A8940F3C123B697578C213BE6DD9E6C8EC7335DCB228FD1EDF4A39152CBCAAF8C0398828041055F94CEEEC7E21340780FE41BD",16)), // y
+ mod_q); // q
+
+ parameters[RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetB] = ecParams;
+
+ mod_p = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7",16); //p
+ mod_q = new BigInteger("3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC98CDBA46506AB004C33A9FF5147502CC8EDA9E7A769A12694623CEF47F023ED",16); //q
+ curve = new FpCurve(
+ mod_p, // p
+ new BigInteger("DC9203E514A721875485A529D2C722FB187BC8980EB866644DE41C68E143064546E861C0E2C9EDD92ADE71F46FCF50FF2AD97F951FDA9F2A2EB6546F39689BD3",16), // a
+ new BigInteger("B4C4EE28CEBC6C2C8AC12952CF37F16AC7EFB6A9F69F4B57FFDA2E4F0DE5ADE038CBC2FFF719D2C18DE0284B8BFEF3B52B8CC7A5F5BF0A3C8D2319A5312557E1",16), // b
+ mod_q,
+ BigInteger.One);
+
+ ecParams = new ECDomainParameters(
+ curve,
+ curve.CreatePoint(
+ new BigInteger("E2E31EDFC23DE7BDEBE241CE593EF5DE2295B7A9CBAEF021D385F7074CEA043AA27272A7AE602BF2A7B9033DB9ED3610C6FB85487EAE97AAC5BC7928C1950148", 16), // x
+ new BigInteger("F5CE40D95B5EB899ABBCCFF5911CB8577939804D6527378B8C108C3D2090FF9BE18E2D33E3021ED2EF32D85822423B6304F726AA854BAE07D0396E9A9ADDC40F",16)), // y
+ mod_q); // q
+
+ parameters[RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetC] = ecParams;
+
objIds["GostR3410-2001-CryptoPro-A"] = CryptoProObjectIdentifiers.GostR3410x2001CryptoProA;
objIds["GostR3410-2001-CryptoPro-B"] = CryptoProObjectIdentifiers.GostR3410x2001CryptoProB;
objIds["GostR3410-2001-CryptoPro-C"] = CryptoProObjectIdentifiers.GostR3410x2001CryptoProC;
objIds["GostR3410-2001-CryptoPro-XchA"] = CryptoProObjectIdentifiers.GostR3410x2001CryptoProXchA;
objIds["GostR3410-2001-CryptoPro-XchB"] = CryptoProObjectIdentifiers.GostR3410x2001CryptoProXchB;
+ objIds["Tc26-Gost-3410-12-256-paramSetA"] = RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256_paramSetA;
+ objIds["Tc26-Gost-3410-12-512-paramSetA"] = RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetA;
+ objIds["Tc26-Gost-3410-12-512-paramSetB"] = RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetB;
+ objIds["Tc26-Gost-3410-12-512-paramSetC"] = RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetC;
names[CryptoProObjectIdentifiers.GostR3410x2001CryptoProA] = "GostR3410-2001-CryptoPro-A";
names[CryptoProObjectIdentifiers.GostR3410x2001CryptoProB] = "GostR3410-2001-CryptoPro-B";
names[CryptoProObjectIdentifiers.GostR3410x2001CryptoProC] = "GostR3410-2001-CryptoPro-C";
names[CryptoProObjectIdentifiers.GostR3410x2001CryptoProXchA] = "GostR3410-2001-CryptoPro-XchA";
names[CryptoProObjectIdentifiers.GostR3410x2001CryptoProXchB] = "GostR3410-2001-CryptoPro-XchB";
+ names[RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256_paramSetA] = "Tc26-Gost-3410-12-256-paramSetA";
+ names[RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetA] = "Tc26-Gost-3410-12-512-paramSetA";
+ names[RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetB] = "Tc26-Gost-3410-12-512-paramSetB";
+ names[RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetC] = "Tc26-Gost-3410-12-512-paramSetC";
}
/**
diff --git a/crypto/src/asn1/esf/SignerLocation.cs b/crypto/src/asn1/esf/SignerLocation.cs
index d2cef51bb..16dbcd01f 100644
--- a/crypto/src/asn1/esf/SignerLocation.cs
+++ b/crypto/src/asn1/esf/SignerLocation.cs
@@ -1,7 +1,7 @@
using System;
using System.Collections;
-using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X500;
namespace Org.BouncyCastle.Asn1.Esf
{
@@ -20,10 +20,9 @@ namespace Org.BouncyCastle.Asn1.Esf
public class SignerLocation
: Asn1Encodable
{
- // TODO Should these be using DirectoryString?
- private DerUtf8String countryName;
- private DerUtf8String localityName;
- private Asn1Sequence postalAddress;
+ private DirectoryString countryName;
+ private DirectoryString localityName;
+ private Asn1Sequence postalAddress;
public SignerLocation(
Asn1Sequence seq)
@@ -33,10 +32,10 @@ namespace Org.BouncyCastle.Asn1.Esf
switch (obj.TagNo)
{
case 0:
- this.countryName = DerUtf8String.GetInstance(obj, true);
+ this.countryName = DirectoryString.GetInstance(obj, true);
break;
case 1:
- this.localityName = DerUtf8String.GetInstance(obj, true);
+ this.localityName = DirectoryString.GetInstance(obj, true);
break;
case 2:
bool isExplicit = obj.IsExplicit(); // handle erroneous implicitly tagged sequences
@@ -50,33 +49,36 @@ namespace Org.BouncyCastle.Asn1.Esf
}
}
- public SignerLocation(
- DerUtf8String countryName,
- DerUtf8String localityName,
- Asn1Sequence postalAddress)
- {
- if (postalAddress != null && postalAddress.Count > 6)
- {
- throw new ArgumentException("postal address must contain less than 6 strings");
- }
-
- if (countryName != null)
- {
- this.countryName = DerUtf8String.GetInstance(countryName.ToAsn1Object());
- }
-
- if (localityName != null)
- {
- this.localityName = DerUtf8String.GetInstance(localityName.ToAsn1Object());
- }
-
- if (postalAddress != null)
- {
- this.postalAddress = (Asn1Sequence) postalAddress.ToAsn1Object();
- }
- }
-
- public static SignerLocation GetInstance(
+ private SignerLocation(
+ DirectoryString countryName,
+ DirectoryString localityName,
+ Asn1Sequence postalAddress)
+ {
+ if (postalAddress != null && postalAddress.Count > 6)
+ throw new ArgumentException("postal address must contain less than 6 strings");
+
+ this.countryName = countryName;
+ this.localityName = localityName;
+ this.postalAddress = postalAddress;
+ }
+
+ public SignerLocation(
+ DirectoryString countryName,
+ DirectoryString localityName,
+ DirectoryString[] postalAddress)
+ : this(countryName, localityName, new DerSequence(postalAddress))
+ {
+ }
+
+ public SignerLocation(
+ DerUtf8String countryName,
+ DerUtf8String localityName,
+ Asn1Sequence postalAddress)
+ : this(DirectoryString.GetInstance(countryName), DirectoryString.GetInstance(localityName), postalAddress)
+ {
+ }
+
+ public static SignerLocation GetInstance(
object obj)
{
if (obj == null || obj is SignerLocation)
@@ -87,15 +89,41 @@ namespace Org.BouncyCastle.Asn1.Esf
return new SignerLocation(Asn1Sequence.GetInstance(obj));
}
+ public DirectoryString Country
+ {
+ get { return countryName; }
+ }
+
+ public DirectoryString Locality
+ {
+ get { return localityName; }
+ }
+
+ public DirectoryString[] GetPostal()
+ {
+ if (postalAddress == null)
+ return null;
+
+ DirectoryString[] dirStrings = new DirectoryString[postalAddress.Count];
+ for (int i = 0; i != dirStrings.Length; i++)
+ {
+ dirStrings[i] = DirectoryString.GetInstance(postalAddress[i]);
+ }
+
+ return dirStrings;
+ }
+
+ [Obsolete("Use 'Country' property instead")]
public DerUtf8String CountryName
{
- get { return countryName; }
+ get { return countryName == null ? null : new DerUtf8String(countryName.GetString()); }
}
- public DerUtf8String LocalityName
- {
- get { return localityName; }
- }
+ [Obsolete("Use 'Locality' property instead")]
+ public DerUtf8String LocalityName
+ {
+ get { return localityName == null ? null : new DerUtf8String(localityName.GetString()); }
+ }
public Asn1Sequence PostalAddress
{
diff --git a/crypto/src/asn1/rosstandart/RosstandartObjectIdentifiers.cs b/crypto/src/asn1/rosstandart/RosstandartObjectIdentifiers.cs
new file mode 100644
index 000000000..86fedb7bb
--- /dev/null
+++ b/crypto/src/asn1/rosstandart/RosstandartObjectIdentifiers.cs
@@ -0,0 +1,47 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Rosstandart
+{
+ public abstract class RosstandartObjectIdentifiers
+ {
+ public static readonly DerObjectIdentifier rosstandart = new DerObjectIdentifier("1.2.643.7");
+
+ public static readonly DerObjectIdentifier id_tc26 = rosstandart.Branch("1");
+
+ public static readonly DerObjectIdentifier id_tc26_gost_3411_12_256 = id_tc26.Branch("1.2.2");
+
+ public static readonly DerObjectIdentifier id_tc26_gost_3411_12_512 = id_tc26.Branch("1.2.3");
+
+ public static readonly DerObjectIdentifier id_tc26_hmac_gost_3411_12_256 = id_tc26.Branch("1.4.1");
+
+ public static readonly DerObjectIdentifier id_tc26_hmac_gost_3411_12_512 = id_tc26.Branch("1.4.2");
+
+ public static readonly DerObjectIdentifier id_tc26_gost_3410_12_256 = id_tc26.Branch("1.1.1");
+
+ public static readonly DerObjectIdentifier id_tc26_gost_3410_12_512 = id_tc26.Branch("1.1.2");
+
+ public static readonly DerObjectIdentifier id_tc26_signwithdigest_gost_3410_12_256 = id_tc26.Branch("1.3.2");
+
+ public static readonly DerObjectIdentifier id_tc26_signwithdigest_gost_3410_12_512 = id_tc26.Branch("1.3.3");
+
+ public static readonly DerObjectIdentifier id_tc26_agreement = id_tc26.Branch("1.6");
+
+ public static readonly DerObjectIdentifier id_tc26_agreement_gost_3410_12_256 = id_tc26_agreement.Branch("1");
+
+ public static readonly DerObjectIdentifier id_tc26_agreement_gost_3410_12_512 = id_tc26_agreement.Branch("2");
+
+ public static readonly DerObjectIdentifier id_tc26_gost_3410_12_256_paramSet = id_tc26.Branch("2.1.1");
+
+ public static readonly DerObjectIdentifier id_tc26_gost_3410_12_256_paramSetA = id_tc26_gost_3410_12_256_paramSet.Branch("1");
+
+ public static readonly DerObjectIdentifier id_tc26_gost_3410_12_512_paramSet = id_tc26.Branch("2.1.2");
+
+ public static readonly DerObjectIdentifier id_tc26_gost_3410_12_512_paramSetA = id_tc26_gost_3410_12_512_paramSet.Branch("1");
+
+ public static readonly DerObjectIdentifier id_tc26_gost_3410_12_512_paramSetB = id_tc26_gost_3410_12_512_paramSet.Branch("2");
+
+ public static readonly DerObjectIdentifier id_tc26_gost_3410_12_512_paramSetC = id_tc26_gost_3410_12_512_paramSet.Branch("3");
+
+ public static readonly DerObjectIdentifier id_tc26_gost_28147_param_Z = id_tc26.Branch("2.5.1.1");
+ }
+}
diff --git a/crypto/src/asn1/x500/DirectoryString.cs b/crypto/src/asn1/x500/DirectoryString.cs
index d907c6456..6585fcdf5 100644
--- a/crypto/src/asn1/x500/DirectoryString.cs
+++ b/crypto/src/asn1/x500/DirectoryString.cs
@@ -9,15 +9,12 @@ namespace Org.BouncyCastle.Asn1.X500
{
private readonly DerStringBase str;
- public static DirectoryString GetInstance(
- object obj)
+ public static DirectoryString GetInstance(object obj)
{
- if (obj is DirectoryString)
- {
+ if (obj == null || obj is DirectoryString)
return (DirectoryString) obj;
- }
- if (obj is DerStringBase)
+ if (obj is DerStringBase)
{
if (obj is DerT61String
|| obj is DerPrintableString
diff --git a/crypto/src/asn1/x9/ECNamedCurveTable.cs b/crypto/src/asn1/x9/ECNamedCurveTable.cs
index 317ef17b4..f91bded18 100644
--- a/crypto/src/asn1/x9/ECNamedCurveTable.cs
+++ b/crypto/src/asn1/x9/ECNamedCurveTable.cs
@@ -2,10 +2,12 @@
using System.Collections;
using Org.BouncyCastle.Asn1.Anssi;
+using Org.BouncyCastle.Asn1.CryptoPro;
using Org.BouncyCastle.Asn1.GM;
using Org.BouncyCastle.Asn1.Nist;
using Org.BouncyCastle.Asn1.Sec;
using Org.BouncyCastle.Asn1.TeleTrust;
+using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Collections;
@@ -44,6 +46,10 @@ namespace Org.BouncyCastle.Asn1.X9
}
if (ecP == null)
{
+ ecP = FromDomainParameters(ECGost3410NamedCurves.GetByName(name));
+ }
+ if (ecP == null)
+ {
ecP = GMNamedCurves.GetByName(name);
}
return ecP;
@@ -70,6 +76,10 @@ namespace Org.BouncyCastle.Asn1.X9
}
if (name == null)
{
+ name = ECGost3410NamedCurves.GetName(oid);
+ }
+ if (name == null)
+ {
name = GMNamedCurves.GetName(oid);
}
return name;
@@ -102,6 +112,10 @@ namespace Org.BouncyCastle.Asn1.X9
}
if (oid == null)
{
+ oid = ECGost3410NamedCurves.GetOid(name);
+ }
+ if (oid == null)
+ {
oid = GMNamedCurves.GetOid(name);
}
return oid;
@@ -134,6 +148,10 @@ namespace Org.BouncyCastle.Asn1.X9
}
if (ecP == null)
{
+ ecP = FromDomainParameters(ECGost3410NamedCurves.GetByOid(oid));
+ }
+ if (ecP == null)
+ {
ecP = GMNamedCurves.GetByOid(oid);
}
return ecP;
@@ -154,9 +172,15 @@ namespace Org.BouncyCastle.Asn1.X9
CollectionUtilities.AddRange(v, NistNamedCurves.Names);
CollectionUtilities.AddRange(v, TeleTrusTNamedCurves.Names);
CollectionUtilities.AddRange(v, AnssiNamedCurves.Names);
+ CollectionUtilities.AddRange(v, ECGost3410NamedCurves.Names);
CollectionUtilities.AddRange(v, GMNamedCurves.Names);
return v;
}
}
+
+ private static X9ECParameters FromDomainParameters(ECDomainParameters dp)
+ {
+ return dp == null ? null : new X9ECParameters(dp.Curve, dp.G, dp.N, dp.H, dp.GetSeed());
+ }
}
}
diff --git a/crypto/src/crypto/agreement/SM2KeyExchange.cs b/crypto/src/crypto/agreement/SM2KeyExchange.cs
new file mode 100644
index 000000000..1cfcd6a3a
--- /dev/null
+++ b/crypto/src/crypto/agreement/SM2KeyExchange.cs
@@ -0,0 +1,272 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Agreement
+{
+ /// <summary>
+ /// SM2 Key Exchange protocol - based on https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02
+ /// </summary>
+ public class SM2KeyExchange
+ {
+ private readonly IDigest mDigest;
+
+ private byte[] mUserID;
+ private ECPrivateKeyParameters mStaticKey;
+ private ECPoint mStaticPubPoint;
+ private ECPoint mEphemeralPubPoint;
+ private ECDomainParameters mECParams;
+ private int mW;
+ private ECPrivateKeyParameters mEphemeralKey;
+ private bool mInitiator;
+
+ public SM2KeyExchange()
+ : this(new SM3Digest())
+ {
+ }
+
+ public SM2KeyExchange(IDigest digest)
+ {
+ this.mDigest = digest;
+ }
+
+ public virtual void Init(ICipherParameters privParam)
+ {
+ SM2KeyExchangePrivateParameters baseParam;
+
+ if (privParam is ParametersWithID)
+ {
+ baseParam = (SM2KeyExchangePrivateParameters)((ParametersWithID)privParam).Parameters;
+ mUserID = ((ParametersWithID)privParam).GetID();
+ }
+ else
+ {
+ baseParam = (SM2KeyExchangePrivateParameters)privParam;
+ mUserID = new byte[0];
+ }
+
+ mInitiator = baseParam.IsInitiator;
+ mStaticKey = baseParam.StaticPrivateKey;
+ mEphemeralKey = baseParam.EphemeralPrivateKey;
+ mECParams = mStaticKey.Parameters;
+ mStaticPubPoint = baseParam.StaticPublicPoint;
+ mEphemeralPubPoint = baseParam.EphemeralPublicPoint;
+ mW = mECParams.Curve.FieldSize / 2 - 1;
+ }
+
+ public virtual byte[] CalculateKey(int kLen, ICipherParameters pubParam)
+ {
+ SM2KeyExchangePublicParameters otherPub;
+ byte[] otherUserID;
+
+ if (pubParam is ParametersWithID)
+ {
+ otherPub = (SM2KeyExchangePublicParameters)((ParametersWithID)pubParam).Parameters;
+ otherUserID = ((ParametersWithID)pubParam).GetID();
+ }
+ else
+ {
+ otherPub = (SM2KeyExchangePublicParameters)pubParam;
+ otherUserID = new byte[0];
+ }
+
+ byte[] za = GetZ(mDigest, mUserID, mStaticPubPoint);
+ byte[] zb = GetZ(mDigest, otherUserID, otherPub.StaticPublicKey.Q);
+
+ ECPoint U = CalculateU(otherPub);
+
+ byte[] rv;
+ if (mInitiator)
+ {
+ rv = Kdf(U, za, zb, kLen);
+ }
+ else
+ {
+ rv = Kdf(U, zb, za, kLen);
+ }
+
+ return rv;
+ }
+
+ public virtual byte[][] CalculateKeyWithConfirmation(int kLen, byte[] confirmationTag, ICipherParameters pubParam)
+ {
+ SM2KeyExchangePublicParameters otherPub;
+ byte[] otherUserID;
+
+ if (pubParam is ParametersWithID)
+ {
+ otherPub = (SM2KeyExchangePublicParameters)((ParametersWithID)pubParam).Parameters;
+ otherUserID = ((ParametersWithID)pubParam).GetID();
+ }
+ else
+ {
+ otherPub = (SM2KeyExchangePublicParameters)pubParam;
+ otherUserID = new byte[0];
+ }
+
+ if (mInitiator && confirmationTag == null)
+ throw new ArgumentException("if initiating, confirmationTag must be set");
+
+ byte[] za = GetZ(mDigest, mUserID, mStaticPubPoint);
+ byte[] zb = GetZ(mDigest, otherUserID, otherPub.StaticPublicKey.Q);
+
+ ECPoint U = CalculateU(otherPub);
+
+ byte[] rv;
+ if (mInitiator)
+ {
+ rv = Kdf(U, za, zb, kLen);
+
+ byte[] inner = CalculateInnerHash(mDigest, U, za, zb, mEphemeralPubPoint, otherPub.EphemeralPublicKey.Q);
+
+ byte[] s1 = S1(mDigest, U, inner);
+
+ if (!Arrays.ConstantTimeAreEqual(s1, confirmationTag))
+ throw new InvalidOperationException("confirmation tag mismatch");
+
+ return new byte[][] { rv, S2(mDigest, U, inner)};
+ }
+ else
+ {
+ rv = Kdf(U, zb, za, kLen);
+
+ byte[] inner = CalculateInnerHash(mDigest, U, zb, za, otherPub.EphemeralPublicKey.Q, mEphemeralPubPoint);
+
+ return new byte[][] { rv, S1(mDigest, U, inner), S2(mDigest, U, inner) };
+ }
+ }
+
+ protected virtual ECPoint CalculateU(SM2KeyExchangePublicParameters otherPub)
+ {
+ ECPoint p1 = otherPub.StaticPublicKey.Q;
+ ECPoint p2 = otherPub.EphemeralPublicKey.Q;
+
+ BigInteger x1 = Reduce(mEphemeralPubPoint.AffineXCoord.ToBigInteger());
+ BigInteger x2 = Reduce(p2.AffineXCoord.ToBigInteger());
+ BigInteger tA = mStaticKey.D.Add(x1.Multiply(mEphemeralKey.D));
+ BigInteger k1 = mECParams.H.Multiply(tA).Mod(mECParams.N);
+ BigInteger k2 = k1.Multiply(x2).Mod(mECParams.N);
+
+ return ECAlgorithms.SumOfTwoMultiplies(p1, k1, p2, k2).Normalize();
+ }
+
+ protected virtual byte[] Kdf(ECPoint u, byte[] za, byte[] zb, int klen)
+ {
+ int digestSize = mDigest.GetDigestSize();
+ byte[] buf = new byte[System.Math.Max(4, digestSize)];
+ byte[] rv = new byte[(klen + 7) / 8];
+ int off = 0;
+
+ IMemoable memo = mDigest as IMemoable;
+ IMemoable copy = null;
+
+ if (memo != null)
+ {
+ AddFieldElement(mDigest, u.AffineXCoord);
+ AddFieldElement(mDigest, u.AffineYCoord);
+ mDigest.BlockUpdate(za, 0, za.Length);
+ mDigest.BlockUpdate(zb, 0, zb.Length);
+ copy = memo.Copy();
+ }
+
+ uint ct = 0;
+
+ while (off < rv.Length)
+ {
+ if (memo != null)
+ {
+ memo.Reset(copy);
+ }
+ else
+ {
+ AddFieldElement(mDigest, u.AffineXCoord);
+ AddFieldElement(mDigest, u.AffineYCoord);
+ mDigest.BlockUpdate(za, 0, za.Length);
+ mDigest.BlockUpdate(zb, 0, zb.Length);
+ }
+
+ Pack.UInt32_To_BE(++ct, buf, 0);
+ mDigest.BlockUpdate(buf, 0, 4);
+ mDigest.DoFinal(buf, 0);
+
+ int copyLen = System.Math.Min(digestSize, rv.Length - off);
+ Array.Copy(buf, 0, rv, off, copyLen);
+ off += copyLen;
+ }
+
+ return rv;
+ }
+
+ //x1~=2^w+(x1 AND (2^w-1))
+ private BigInteger Reduce(BigInteger x)
+ {
+ return x.And(BigInteger.One.ShiftLeft(mW).Subtract(BigInteger.One)).SetBit(mW);
+ }
+
+ private byte[] S1(IDigest digest, ECPoint u, byte[] inner)
+ {
+ digest.Update((byte)0x02);
+ AddFieldElement(digest, u.AffineYCoord);
+ digest.BlockUpdate(inner, 0, inner.Length);
+
+ return DigestUtilities.DoFinal(digest);
+ }
+
+ private byte[] CalculateInnerHash(IDigest digest, ECPoint u, byte[] za, byte[] zb, ECPoint p1, ECPoint p2)
+ {
+ AddFieldElement(digest, u.AffineXCoord);
+ digest.BlockUpdate(za, 0, za.Length);
+ digest.BlockUpdate(zb, 0, zb.Length);
+ AddFieldElement(digest, p1.AffineXCoord);
+ AddFieldElement(digest, p1.AffineYCoord);
+ AddFieldElement(digest, p2.AffineXCoord);
+ AddFieldElement(digest, p2.AffineYCoord);
+
+ return DigestUtilities.DoFinal(digest);
+ }
+
+ private byte[] S2(IDigest digest, ECPoint u, byte[] inner)
+ {
+ digest.Update((byte)0x03);
+ AddFieldElement(digest, u.AffineYCoord);
+ digest.BlockUpdate(inner, 0, inner.Length);
+
+ return DigestUtilities.DoFinal(digest);
+ }
+
+ private byte[] GetZ(IDigest digest, byte[] userID, ECPoint pubPoint)
+ {
+ AddUserID(digest, userID);
+
+ AddFieldElement(digest, mECParams.Curve.A);
+ AddFieldElement(digest, mECParams.Curve.B);
+ AddFieldElement(digest, mECParams.G.AffineXCoord);
+ AddFieldElement(digest, mECParams.G.AffineYCoord);
+ AddFieldElement(digest, pubPoint.AffineXCoord);
+ AddFieldElement(digest, pubPoint.AffineYCoord);
+
+ return DigestUtilities.DoFinal(digest);
+ }
+
+ private void AddUserID(IDigest digest, byte[] userID)
+ {
+ uint len = (uint)(userID.Length * 8);
+
+ digest.Update((byte)(len >> 8));
+ digest.Update((byte)len);
+ digest.BlockUpdate(userID, 0, userID.Length);
+ }
+
+ private void AddFieldElement(IDigest digest, ECFieldElement v)
+ {
+ byte[] p = v.GetEncoded();
+ digest.BlockUpdate(p, 0, p.Length);
+ }
+ }
+}
diff --git a/crypto/src/crypto/agreement/kdf/ConcatenationKdfGenerator.cs b/crypto/src/crypto/agreement/kdf/ConcatenationKdfGenerator.cs
new file mode 100644
index 000000000..d88f4dfdb
--- /dev/null
+++ b/crypto/src/crypto/agreement/kdf/ConcatenationKdfGenerator.cs
@@ -0,0 +1,100 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Agreement.Kdf
+{
+ /**
+ * Generator for Concatenation Key Derivation Function defined in NIST SP 800-56A, Sect 5.8.1
+ */
+ public class ConcatenationKdfGenerator
+ : IDerivationFunction
+ {
+ private readonly IDigest mDigest;
+
+ private byte[] mShared;
+ private byte[] mOtherInfo;
+ private int mHLen;
+
+ /**
+ * @param digest the digest to be used as the source of generated bytes
+ */
+ public ConcatenationKdfGenerator(IDigest digest)
+ {
+ this.mDigest = digest;
+ this.mHLen = digest.GetDigestSize();
+ }
+
+ public virtual void Init(IDerivationParameters param)
+ {
+ if (!(param is KdfParameters))
+ throw new ArgumentException("KDF parameters required for ConcatenationKdfGenerator");
+
+ KdfParameters p = (KdfParameters)param;
+
+ mShared = p.GetSharedSecret();
+ mOtherInfo = p.GetIV();
+ }
+
+ /**
+ * return the underlying digest.
+ */
+ public virtual IDigest Digest
+ {
+ get { return mDigest; }
+ }
+
+ /**
+ * fill len bytes of the output buffer with bytes generated from
+ * the derivation function.
+ *
+ * @throws DataLengthException if the out buffer is too small.
+ */
+ public virtual int GenerateBytes(byte[] outBytes, int outOff, int len)
+ {
+ if ((outBytes.Length - len) < outOff)
+ throw new DataLengthException("output buffer too small");
+
+ byte[] hashBuf = new byte[mHLen];
+ byte[] C = new byte[4];
+ uint counter = 1;
+ int outputLen = 0;
+
+ mDigest.Reset();
+
+ if (len > mHLen)
+ {
+ do
+ {
+ Pack.UInt32_To_BE(counter, C);
+
+ mDigest.BlockUpdate(C, 0, C.Length);
+ mDigest.BlockUpdate(mShared, 0, mShared.Length);
+ mDigest.BlockUpdate(mOtherInfo, 0, mOtherInfo.Length);
+
+ mDigest.DoFinal(hashBuf, 0);
+
+ Array.Copy(hashBuf, 0, outBytes, outOff + outputLen, mHLen);
+ outputLen += mHLen;
+ }
+ while ((counter++) < (len / mHLen));
+ }
+
+ if (outputLen < len)
+ {
+ Pack.UInt32_To_BE(counter, C);
+
+ mDigest.BlockUpdate(C, 0, C.Length);
+ mDigest.BlockUpdate(mShared, 0, mShared.Length);
+ mDigest.BlockUpdate(mOtherInfo, 0, mOtherInfo.Length);
+
+ mDigest.DoFinal(hashBuf, 0);
+
+ Array.Copy(hashBuf, 0, outBytes, outOff + outputLen, len - outputLen);
+ }
+
+ return len;
+ }
+ }
+}
diff --git a/crypto/src/crypto/digests/DSTU7564Digest.cs b/crypto/src/crypto/digests/DSTU7564Digest.cs
index 9de41dd6b..e641af6c2 100644
--- a/crypto/src/crypto/digests/DSTU7564Digest.cs
+++ b/crypto/src/crypto/digests/DSTU7564Digest.cs
@@ -11,48 +11,39 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Digests
{
- /**
- * implementation of Ukrainian DSTU 7564 hash function
- */
- public class Dstu7564Digest : IDigest, IMemoable
- {
- private const int ROWS = 8;
- private const int REDUCTION_POLYNOMIAL = 0x011d;
- private const int BITS_IN_BYTE = 8;
-
-
- private const int NB_512 = 8; //Number of 8-byte words in state for <=256-bit hash code.
- private const int NB_1024 = 16; //Number of 8-byte words in state for <=512-bit hash code.
-
- private const int NR_512 = 10; //Number of rounds for 512-bit state.
- private const int NR_1024 = 14; //Number of rounds for 1024-bit state.
-
- private const int STATE_BYTE_SIZE_512 = ROWS * NB_512;
- private const int STATE_BYTE_SIZE_1024 = ROWS * NB_1024;
-
- private int hashSize;
- private int blockSize;
-
-
-
- private int columns;
- private int rounds;
-
-
- private byte[] padded_;
-
- private byte[][] state_;
-
+ /**
+ * implementation of Ukrainian DSTU 7564 hash function
+ */
+ public class Dstu7564Digest : IDigest, IMemoable
+ {
+ private const int ROWS = 8;
+ private const int BITS_IN_BYTE = 8;
+
+ private const int NB_512 = 8; //Number of 8-byte words in state for <=256-bit hash code.
+ private const int NB_1024 = 16; //Number of 8-byte words in state for <=512-bit hash code.
+
+ private const int NR_512 = 10; //Number of rounds for 512-bit state.
+ private const int NR_1024 = 14; //Number of rounds for 1024-bit state.
+
+ private const int STATE_BYTE_SIZE_512 = ROWS * NB_512;
+ private const int STATE_BYTE_SIZE_1024 = ROWS * NB_1024;
+
+ private int hashSize;
+ private int blockSize;
+ private int columns;
+ private int rounds;
+ private byte[] padded_;
+ private byte[][] state_;
private ulong inputLength;
private int bufOff;
private byte[] buf;
public Dstu7564Digest(Dstu7564Digest digest)
{
- copyIn(digest);
+ CopyIn(digest);
}
- private void copyIn(Dstu7564Digest digest)
+ private void CopyIn(Dstu7564Digest digest)
{
this.hashSize = digest.hashSize;
this.blockSize = digest.blockSize;
@@ -62,6 +53,7 @@ namespace Org.BouncyCastle.Crypto.Digests
this.padded_ = Arrays.Clone(digest.padded_);
this.state_ = new byte[digest.state_.Length][];
+
for (int i = 0; i != this.state_.Length; i++)
{
this.state_[i] = Arrays.Clone(digest.state_[i]);
@@ -73,56 +65,51 @@ namespace Org.BouncyCastle.Crypto.Digests
}
public Dstu7564Digest(int hashSizeBits)
- {
- if (hashSizeBits == 256 || hashSizeBits == 384 || hashSizeBits == 512)
- {
- this.hashSize = hashSizeBits / 8;
- }
- else
- {
- throw new ArgumentException("Hash size is not recommended. Use 256 or 384 or 512 size");
- }
-
- if (hashSizeBits > 256)
- {
- this.blockSize = 1024 / 8;
- this.columns = NB_1024;
- this.rounds = NR_1024;
- this.state_ = new byte[STATE_BYTE_SIZE_1024][];
-
- }
- else
- {
- this.blockSize = 512 / 8;
- this.columns = NB_512;
- this.rounds = NR_512;
- this.state_ = new byte[STATE_BYTE_SIZE_512][];
-
- }
-
- //Console.WriteLine("length: " + state_.Length);
-
- for (int i = 0; i < state_.Length; i++)
- {
- this.state_[i] = new byte[columns];
- }
-
- this.state_[0][0] = (byte)state_.Length;
-
- this.hashSize = hashSizeBits / 8;
-
- this.padded_ = null;
- this.buf = new byte[blockSize];
- }
+ {
+ if (hashSizeBits == 256 || hashSizeBits == 384 || hashSizeBits == 512)
+ {
+ this.hashSize = hashSizeBits / 8;
+ }
+ else
+ {
+ throw new ArgumentException("Hash size is not recommended. Use 256 or 384 or 512 size");
+ }
+
+ if (hashSizeBits > 256)
+ {
+ this.blockSize = 1024 / 8;
+ this.columns = NB_1024;
+ this.rounds = NR_1024;
+ this.state_ = new byte[STATE_BYTE_SIZE_1024][];
+ }
+ else
+ {
+ this.blockSize = 512 / 8;
+ this.columns = NB_512;
+ this.rounds = NR_512;
+ this.state_ = new byte[STATE_BYTE_SIZE_512][];
+ }
+
+ for (int i = 0; i < state_.Length; i++)
+ {
+ this.state_[i] = new byte[columns];
+ }
- public string AlgorithmName
- {
- get { return "DSTU7564"; }
- }
+ this.state_[0][0] = (byte)state_.Length;
+ this.hashSize = hashSizeBits / 8;
- public virtual void BlockUpdate(byte[] input, int inOff, int length)
- {
+ this.padded_ = null;
+ this.buf = new byte[blockSize];
+ }
+
+ public virtual string AlgorithmName
+ {
+ get { return "DSTU7564"; }
+ }
+
+ public virtual void BlockUpdate(byte[] input, int inOff, int length)
+ {
while (bufOff != 0 && length > 0)
{
Update(input[inOff++]);
@@ -147,10 +134,8 @@ namespace Org.BouncyCastle.Crypto.Digests
}
}
- protected byte[] Pad(byte[] input, int inOff, int length)
- {
- //Console.WriteLine(length);
-
+ protected virtual byte[] Pad(byte[] input, int inOff, int length)
+ {
byte[] padded;
if (blockSize - length < 13) // terminator byte + 96 bits of length
{
@@ -161,55 +146,48 @@ namespace Org.BouncyCastle.Crypto.Digests
padded = new byte[blockSize];
}
+ Array.Copy(input, inOff, padded, 0, length);
+ padded[length] = 0x80;
+ Pack.UInt64_To_LE(inputLength * 8, padded, padded.Length - 12);
- Array.Copy(input, inOff, padded, 0, length);
- padded[length] = 0x80;
- Pack.UInt64_To_LE(inputLength * 8, padded, padded.Length - 12);
-
- return padded;
- }
-
- protected void ProcessBlock(byte[] input, int inOff)
- {
- byte[][] temp1 = new byte[STATE_BYTE_SIZE_1024][];
- byte[][] temp2 = new byte[STATE_BYTE_SIZE_1024][];
-
- for (int i = 0; i < state_.Length; i++)
- {
- temp1[i] = new byte[ROWS];
- temp2[i] = new byte[ROWS];
- }
-
- for (int i = 0; i < ROWS; ++i)
- {
- for (int j = 0; j < columns; ++j)
- {
- //Console.WriteLine("row = {0}, column = {1}", i, j);
-
- temp1[j][i] = (byte)(state_[j][i] ^ input[j * ROWS + i + inOff]);
- temp2[j][i] = input[j * ROWS + i + inOff];
+ return padded;
+ }
- }
-
- }
+ protected virtual void ProcessBlock(byte[] input, int inOff)
+ {
+ byte[][] temp1 = new byte[columns][];
+ byte[][] temp2 = new byte[columns][];
- P(temp1);
+ int pos = inOff;
+ for (int i = 0; i < columns; i++)
+ {
+ byte[] S = state_[i];
+ byte[] T1 = temp1[i] = new byte[ROWS];
+ byte[] T2 = temp2[i] = new byte[ROWS];
- Q(temp2);
+ for (int j = 0; j < ROWS; ++j)
+ {
+ byte inVal = input[pos++];
+ T1[j] = (byte)(S[j] ^ inVal);
+ T2[j] = inVal;
+ }
+ }
- for (int i = 0; i < ROWS; ++i)
- {
- for (int j = 0; j < columns; ++j)
- {
- state_[j][i] ^= (byte)(temp1[j][i] ^ temp2[j][i]);
+ P(temp1);
+ Q(temp2);
- }
-
- }
- }
+ for (int i = 0; i < columns; ++i)
+ {
+ byte[] S = state_[i], T1 = temp1[i], T2 = temp2[i];
+ for (int j = 0; j < ROWS; ++j)
+ {
+ S[j] ^= (byte)(T1[j] ^ T2[j]);
+ }
+ }
+ }
- public int DoFinal(byte[] output, int outOff)
- {
+ public virtual int DoFinal(byte[] output, int outOff)
+ {
padded_ = Pad(buf, 0, bufOff);
int paddedLen = padded_.Length;
@@ -222,55 +200,43 @@ namespace Org.BouncyCastle.Crypto.Digests
paddedLen -= blockSize;
}
-
- //Console.WriteLine(stateLine.Length);
-
byte[][] temp = new byte[STATE_BYTE_SIZE_1024][];
- for (int i = 0; i < state_.Length; i++)
- {
- temp[i] = new byte[ROWS];
- Array.Copy(state_[i], temp[i], ROWS);
- }
+ for (int i = 0; i < state_.Length; i++)
+ {
+ temp[i] = new byte[ROWS];
+ Array.Copy(state_[i], temp[i], ROWS);
+ }
P(temp);
for (int i = 0; i < ROWS; ++i)
{
- for (int j = 0; j < columns; ++j)
- {
- state_[j][i] ^= temp[j][i];
- //Console.Write("{0:x} ", state_[j][i]);
- }
- //Console.WriteLine();
+ for (int j = 0; j < columns; ++j)
+ {
+ state_[j][i] ^= temp[j][i];
+ }
}
byte[] stateLine = new byte[ROWS * columns];
int stateLineIndex = 0;
- for (int j = 0; j < columns; ++j)
- {
- for (int i = 0; i < ROWS; ++i)
- {
-
- stateLine[stateLineIndex] = state_[j][i];
- stateLineIndex++;
-
- //Console.WriteLine("index = {0}, row = {1}, column = {2}", stateLineIndex, i, j);
-
- }
- }
-
- //Console.WriteLine("final: " + Hex.ToHexString(stateLine));
- //Console.WriteLine(stateLine.Length);
-
- Array.Copy(stateLine, stateLine.Length - hashSize, output, outOff, hashSize);
-
- Reset();
-
- return hashSize;
- }
-
- public void Reset()
- {
+ for (int j = 0; j < columns; ++j)
+ {
+ for (int i = 0; i < ROWS; ++i)
+ {
+ stateLine[stateLineIndex] = state_[j][i];
+ stateLineIndex++;
+ }
+ }
+
+ Array.Copy(stateLine, stateLine.Length - hashSize, output, outOff, hashSize);
+
+ Reset();
+
+ return hashSize;
+ }
+
+ public virtual void Reset()
+ {
for (int bufferIndex = 0; bufferIndex < state_.Length; bufferIndex++)
{
state_[bufferIndex] = new byte[columns];
@@ -289,18 +255,18 @@ namespace Org.BouncyCastle.Crypto.Digests
}
}
- public int GetDigestSize()
- {
- return hashSize;
- }
+ public virtual int GetDigestSize()
+ {
+ return hashSize;
+ }
- public int GetByteLength()
- {
- return blockSize;
- }
+ public virtual int GetByteLength()
+ {
+ return blockSize;
+ }
- public void Update(byte input)
- {
+ public virtual void Update(byte input)
+ {
buf[bufOff++] = input;
if (bufOff == blockSize)
{
@@ -308,255 +274,238 @@ namespace Org.BouncyCastle.Crypto.Digests
bufOff = 0;
}
inputLength++;
- }
-
- void SubBytes(byte[][] state)
- {
- int i, j;
- for (i = 0; i < ROWS; ++i)
- {
- for (j = 0; j < columns; ++j)
- {
- state[j][i] = sBoxes[i % 4][state[j][i]];
- }
- }
- }
-
- void ShiftBytes(byte[][] state)
- {
- int i, j;
- byte[] temp = new byte[NB_1024];
- int shift = -1;
- for (i = 0; i < ROWS; ++i)
- {
- if ((i == ROWS - 1) && (columns == NB_1024))
- {
- shift = 11;
- }
- else
- {
- ++shift;
- }
- for (j = 0; j < columns; ++j)
- {
- temp[(j + shift) % columns] = state[j][i];
- }
- for (j = 0; j < columns; ++j)
- {
- state[j][i] = temp[j];
- }
- }
- }
-
- byte MultiplyGF(byte x, byte y)
- {
- int i;
- byte r = 0;
- byte hbit = 0;
- for (i = 0; i < BITS_IN_BYTE; ++i)
- {
- if ((y & 0x1) == 1)
- {
- r ^= x;
- }
-
- hbit = (byte)(x & 0x80);
-
- x <<= 1;
-
- if (hbit == 0x80)
- {
- x = (byte)((int)x ^ REDUCTION_POLYNOMIAL);
- }
-
- y >>= 1;
- }
- return r;
- }
-
- private void MixColumns(byte[][] state)
- {
- int i, row, col, b;
- byte product;
- byte[] result = new byte[ROWS];
-
- for (col = 0; col < columns; ++col)
- {
- Array.Clear(result, 0, ROWS);
- for (row = ROWS - 1; row >= 0; --row)
- {
- product = 0;
- for (b = ROWS - 1; b >= 0; --b)
- {
- product ^= MultiplyGF(state[col][b], mds_matrix[row][b]);
- }
- result[row] = product;
- }
- for (i = 0; i < ROWS; ++i)
- {
- state[col][i] = result[i];
- }
- }
- }
-
- void AddRoundConstantP(byte[][] state, int round)
- {
- int i;
- for (i = 0; i < columns; ++i)
- {
- state[i][0] ^= (byte)((i * 0x10) ^ round);
- }
- }
-
- void AddRoundConstantQ(byte[][] state, int round)
- {
- int j;
- UInt64[] s = new UInt64[columns];
-
- for (j = 0; j < columns; j++)
- {
- s[j] = Pack.LE_To_UInt64(state[j]);
-
- s[j] = s[j] + (0x00F0F0F0F0F0F0F3UL ^ ((((UInt64)(columns - j - 1) * 0x10UL) ^ (UInt64)round) << (7 * 8)));
-
- state[j] = Pack.UInt64_To_LE(s[j]);
- }
- }
-
- void P(byte[][] state)
- {
- int i;
- for (i = 0; i < rounds; ++i)
- {
- AddRoundConstantP(state, i);
- SubBytes(state);
- ShiftBytes(state);
- MixColumns(state);
- }
- }
-
- void Q(byte[][] state)
- {
- int i;
- for (i = 0; i < rounds; ++i)
- {
- AddRoundConstantQ(state, i);
- SubBytes(state);
- ShiftBytes(state);
- MixColumns(state);
- }
- }
-
- public IMemoable Copy()
+ }
+
+ private void SubBytes(byte[][] state)
+ {
+ int i, j;
+ for (i = 0; i < ROWS; ++i)
+ {
+ for (j = 0; j < columns; ++j)
+ {
+ state[j][i] = sBoxes[i % 4][state[j][i]];
+ }
+ }
+ }
+
+ private void ShiftBytes(byte[][] state)
+ {
+ int i, j;
+ byte[] temp = new byte[NB_1024];
+ int shift = -1;
+ for (i = 0; i < ROWS; ++i)
+ {
+ if ((i == ROWS - 1) && (columns == NB_1024))
+ {
+ shift = 11;
+ }
+ else
+ {
+ ++shift;
+ }
+ for (j = 0; j < columns; ++j)
+ {
+ temp[(j + shift) % columns] = state[j][i];
+ }
+ for (j = 0; j < columns; ++j)
+ {
+ state[j][i] = temp[j];
+ }
+ }
+ }
+
+ /* Pair-wise GF multiplication of 4 byte-pairs (at bits 0, 16, 32, 48 within x, y) */
+ private static ulong MultiplyGFx4(ulong u, ulong v)
+ {
+ ulong r = u & ((v & 0x0001000100010001UL) * 0xFFFFUL);
+
+ for (int i = 1; i < 8; ++i)
+ {
+ u <<= 1;
+ v >>= 1;
+ r ^= u & ((v & 0x0001000100010001L) * 0xFFFFL);
+ }
+
+ // REDUCTION_POLYNOMIAL = 0x011d; /* x^8 + x^4 + x^3 + x^2 + 1 */
+
+ ulong hi = r & 0xFF00FF00FF00FF00UL;
+ r ^= hi ^ (hi >> 4) ^ (hi >> 5) ^ (hi >> 6) ^ (hi >> 8);
+ hi = r & 0x0F000F000F000F00UL;
+ r ^= hi ^ (hi >> 4) ^ (hi >> 5) ^ (hi >> 6) ^ (hi >> 8);
+ return r;
+ }
+
+ private void MixColumns(byte[][] state)
+ {
+ for (int col = 0; col < columns; ++col)
+ {
+ ulong colVal = Pack.LE_To_UInt64(state[col]);
+ ulong colEven = colVal & 0x00FF00FF00FF00FFUL;
+ ulong colOdd = (colVal >> 8) & 0x00FF00FF00FF00FFUL;
+
+ //ulong rowMatrix = (mdsMatrix >> 8) | (mdsMatrix << 56);
+ ulong rowMatrix = mdsMatrix;
+
+ ulong result = 0;
+ for (int row = 7; row >= 0; --row)
+ {
+ ulong product = MultiplyGFx4(colEven, rowMatrix & 0x00FF00FF00FF00FFUL);
+
+ rowMatrix = (rowMatrix >> 8) | (rowMatrix << 56);
+
+ product ^= MultiplyGFx4(colOdd, rowMatrix & 0x00FF00FF00FF00FFUL);
+
+ product ^= (product >> 32);
+ product ^= (product >> 16);
+
+ result <<= 8;
+ result |= (product & 0xFFUL);
+ }
+
+ Pack.UInt64_To_LE(result, state[col]);
+ }
+ }
+
+ private void AddRoundConstantP(byte[][] state, int round)
+ {
+ int i;
+ for (i = 0; i < columns; ++i)
+ {
+ state[i][0] ^= (byte)((i * 0x10) ^ round);
+ }
+ }
+
+ private void AddRoundConstantQ(byte[][] state, int round)
+ {
+ int j;
+ UInt64[] s = new UInt64[columns];
+
+ for (j = 0; j < columns; j++)
+ {
+ s[j] = Pack.LE_To_UInt64(state[j]);
+
+ s[j] = s[j] + (0x00F0F0F0F0F0F0F3UL ^ ((((UInt64)(columns - j - 1) * 0x10UL) ^ (UInt64)round) << (7 * 8)));
+
+ state[j] = Pack.UInt64_To_LE(s[j]);
+ }
+ }
+
+ private void P(byte[][] state)
+ {
+ int i;
+ for (i = 0; i < rounds; ++i)
+ {
+ AddRoundConstantP(state, i);
+ SubBytes(state);
+ ShiftBytes(state);
+ MixColumns(state);
+ }
+ }
+
+ private void Q(byte[][] state)
+ {
+ int i;
+ for (i = 0; i < rounds; ++i)
+ {
+ AddRoundConstantQ(state, i);
+ SubBytes(state);
+ ShiftBytes(state);
+ MixColumns(state);
+ }
+ }
+
+ public virtual IMemoable Copy()
{
return new Dstu7564Digest(this);
}
- public void Reset(IMemoable other)
+ public virtual void Reset(IMemoable other)
{
Dstu7564Digest d = (Dstu7564Digest)other;
- copyIn(d);
+ CopyIn(d);
}
- private readonly byte[][] mds_matrix = new byte[][]
- {
- new byte[] {0x01, 0x01, 0x05, 0x01, 0x08, 0x06, 0x07, 0x04},
- new byte[] {0x04, 0x01, 0x01, 0x05, 0x01, 0x08, 0x06, 0x07},
- new byte[] {0x07, 0x04, 0x01, 0x01, 0x05, 0x01, 0x08, 0x06},
- new byte[] {0x06, 0x07, 0x04, 0x01, 0x01, 0x05, 0x01, 0x08},
- new byte[] {0x08, 0x06, 0x07, 0x04, 0x01, 0x01, 0x05, 0x01},
- new byte[] {0x01, 0x08, 0x06, 0x07, 0x04, 0x01, 0x01, 0x05},
- new byte[] {0x05, 0x01, 0x08, 0x06, 0x07, 0x04, 0x01, 0x01},
- new byte[] {0x01, 0x05, 0x01, 0x08, 0x06, 0x07, 0x04, 0x01}
- };
-
-
-
-
- private readonly byte[][] sBoxes = new byte[][]
- {
- new byte[]
- {
- 0xa8, 0x43, 0x5f, 0x06, 0x6b, 0x75, 0x6c, 0x59, 0x71, 0xdf, 0x87, 0x95, 0x17, 0xf0, 0xd8, 0x09,
- 0x6d, 0xf3, 0x1d, 0xcb, 0xc9, 0x4d, 0x2c, 0xaf, 0x79, 0xe0, 0x97, 0xfd, 0x6f, 0x4b, 0x45, 0x39,
- 0x3e, 0xdd, 0xa3, 0x4f, 0xb4, 0xb6, 0x9a, 0x0e, 0x1f, 0xbf, 0x15, 0xe1, 0x49, 0xd2, 0x93, 0xc6,
- 0x92, 0x72, 0x9e, 0x61, 0xd1, 0x63, 0xfa, 0xee, 0xf4, 0x19, 0xd5, 0xad, 0x58, 0xa4, 0xbb, 0xa1,
- 0xdc, 0xf2, 0x83, 0x37, 0x42, 0xe4, 0x7a, 0x32, 0x9c, 0xcc, 0xab, 0x4a, 0x8f, 0x6e, 0x04, 0x27,
- 0x2e, 0xe7, 0xe2, 0x5a, 0x96, 0x16, 0x23, 0x2b, 0xc2, 0x65, 0x66, 0x0f, 0xbc, 0xa9, 0x47, 0x41,
- 0x34, 0x48, 0xfc, 0xb7, 0x6a, 0x88, 0xa5, 0x53, 0x86, 0xf9, 0x5b, 0xdb, 0x38, 0x7b, 0xc3, 0x1e,
- 0x22, 0x33, 0x24, 0x28, 0x36, 0xc7, 0xb2, 0x3b, 0x8e, 0x77, 0xba, 0xf5, 0x14, 0x9f, 0x08, 0x55,
- 0x9b, 0x4c, 0xfe, 0x60, 0x5c, 0xda, 0x18, 0x46, 0xcd, 0x7d, 0x21, 0xb0, 0x3f, 0x1b, 0x89, 0xff,
- 0xeb, 0x84, 0x69, 0x3a, 0x9d, 0xd7, 0xd3, 0x70, 0x67, 0x40, 0xb5, 0xde, 0x5d, 0x30, 0x91, 0xb1,
- 0x78, 0x11, 0x01, 0xe5, 0x00, 0x68, 0x98, 0xa0, 0xc5, 0x02, 0xa6, 0x74, 0x2d, 0x0b, 0xa2, 0x76,
- 0xb3, 0xbe, 0xce, 0xbd, 0xae, 0xe9, 0x8a, 0x31, 0x1c, 0xec, 0xf1, 0x99, 0x94, 0xaa, 0xf6, 0x26,
- 0x2f, 0xef, 0xe8, 0x8c, 0x35, 0x03, 0xd4, 0x7f, 0xfb, 0x05, 0xc1, 0x5e, 0x90, 0x20, 0x3d, 0x82,
- 0xf7, 0xea, 0x0a, 0x0d, 0x7e, 0xf8, 0x50, 0x1a, 0xc4, 0x07, 0x57, 0xb8, 0x3c, 0x62, 0xe3, 0xc8,
- 0xac, 0x52, 0x64, 0x10, 0xd0, 0xd9, 0x13, 0x0c, 0x12, 0x29, 0x51, 0xb9, 0xcf, 0xd6, 0x73, 0x8d,
- 0x81, 0x54, 0xc0, 0xed, 0x4e, 0x44, 0xa7, 0x2a, 0x85, 0x25, 0xe6, 0xca, 0x7c, 0x8b, 0x56, 0x80
- },
-
- new byte[]
- {
- 0xce, 0xbb, 0xeb, 0x92, 0xea, 0xcb, 0x13, 0xc1, 0xe9, 0x3a, 0xd6, 0xb2, 0xd2, 0x90, 0x17, 0xf8,
- 0x42, 0x15, 0x56, 0xb4, 0x65, 0x1c, 0x88, 0x43, 0xc5, 0x5c, 0x36, 0xba, 0xf5, 0x57, 0x67, 0x8d,
- 0x31, 0xf6, 0x64, 0x58, 0x9e, 0xf4, 0x22, 0xaa, 0x75, 0x0f, 0x02, 0xb1, 0xdf, 0x6d, 0x73, 0x4d,
- 0x7c, 0x26, 0x2e, 0xf7, 0x08, 0x5d, 0x44, 0x3e, 0x9f, 0x14, 0xc8, 0xae, 0x54, 0x10, 0xd8, 0xbc,
- 0x1a, 0x6b, 0x69, 0xf3, 0xbd, 0x33, 0xab, 0xfa, 0xd1, 0x9b, 0x68, 0x4e, 0x16, 0x95, 0x91, 0xee,
- 0x4c, 0x63, 0x8e, 0x5b, 0xcc, 0x3c, 0x19, 0xa1, 0x81, 0x49, 0x7b, 0xd9, 0x6f, 0x37, 0x60, 0xca,
- 0xe7, 0x2b, 0x48, 0xfd, 0x96, 0x45, 0xfc, 0x41, 0x12, 0x0d, 0x79, 0xe5, 0x89, 0x8c, 0xe3, 0x20,
- 0x30, 0xdc, 0xb7, 0x6c, 0x4a, 0xb5, 0x3f, 0x97, 0xd4, 0x62, 0x2d, 0x06, 0xa4, 0xa5, 0x83, 0x5f,
- 0x2a, 0xda, 0xc9, 0x00, 0x7e, 0xa2, 0x55, 0xbf, 0x11, 0xd5, 0x9c, 0xcf, 0x0e, 0x0a, 0x3d, 0x51,
- 0x7d, 0x93, 0x1b, 0xfe, 0xc4, 0x47, 0x09, 0x86, 0x0b, 0x8f, 0x9d, 0x6a, 0x07, 0xb9, 0xb0, 0x98,
- 0x18, 0x32, 0x71, 0x4b, 0xef, 0x3b, 0x70, 0xa0, 0xe4, 0x40, 0xff, 0xc3, 0xa9, 0xe6, 0x78, 0xf9,
- 0x8b, 0x46, 0x80, 0x1e, 0x38, 0xe1, 0xb8, 0xa8, 0xe0, 0x0c, 0x23, 0x76, 0x1d, 0x25, 0x24, 0x05,
- 0xf1, 0x6e, 0x94, 0x28, 0x9a, 0x84, 0xe8, 0xa3, 0x4f, 0x77, 0xd3, 0x85, 0xe2, 0x52, 0xf2, 0x82,
- 0x50, 0x7a, 0x2f, 0x74, 0x53, 0xb3, 0x61, 0xaf, 0x39, 0x35, 0xde, 0xcd, 0x1f, 0x99, 0xac, 0xad,
- 0x72, 0x2c, 0xdd, 0xd0, 0x87, 0xbe, 0x5e, 0xa6, 0xec, 0x04, 0xc6, 0x03, 0x34, 0xfb, 0xdb, 0x59,
- 0xb6, 0xc2, 0x01, 0xf0, 0x5a, 0xed, 0xa7, 0x66, 0x21, 0x7f, 0x8a, 0x27, 0xc7, 0xc0, 0x29, 0xd7
- },
-
- new byte[]
- {
- 0x93, 0xd9, 0x9a, 0xb5, 0x98, 0x22, 0x45, 0xfc, 0xba, 0x6a, 0xdf, 0x02, 0x9f, 0xdc, 0x51, 0x59,
- 0x4a, 0x17, 0x2b, 0xc2, 0x94, 0xf4, 0xbb, 0xa3, 0x62, 0xe4, 0x71, 0xd4, 0xcd, 0x70, 0x16, 0xe1,
- 0x49, 0x3c, 0xc0, 0xd8, 0x5c, 0x9b, 0xad, 0x85, 0x53, 0xa1, 0x7a, 0xc8, 0x2d, 0xe0, 0xd1, 0x72,
- 0xa6, 0x2c, 0xc4, 0xe3, 0x76, 0x78, 0xb7, 0xb4, 0x09, 0x3b, 0x0e, 0x41, 0x4c, 0xde, 0xb2, 0x90,
- 0x25, 0xa5, 0xd7, 0x03, 0x11, 0x00, 0xc3, 0x2e, 0x92, 0xef, 0x4e, 0x12, 0x9d, 0x7d, 0xcb, 0x35,
- 0x10, 0xd5, 0x4f, 0x9e, 0x4d, 0xa9, 0x55, 0xc6, 0xd0, 0x7b, 0x18, 0x97, 0xd3, 0x36, 0xe6, 0x48,
- 0x56, 0x81, 0x8f, 0x77, 0xcc, 0x9c, 0xb9, 0xe2, 0xac, 0xb8, 0x2f, 0x15, 0xa4, 0x7c, 0xda, 0x38,
- 0x1e, 0x0b, 0x05, 0xd6, 0x14, 0x6e, 0x6c, 0x7e, 0x66, 0xfd, 0xb1, 0xe5, 0x60, 0xaf, 0x5e, 0x33,
- 0x87, 0xc9, 0xf0, 0x5d, 0x6d, 0x3f, 0x88, 0x8d, 0xc7, 0xf7, 0x1d, 0xe9, 0xec, 0xed, 0x80, 0x29,
- 0x27, 0xcf, 0x99, 0xa8, 0x50, 0x0f, 0x37, 0x24, 0x28, 0x30, 0x95, 0xd2, 0x3e, 0x5b, 0x40, 0x83,
- 0xb3, 0x69, 0x57, 0x1f, 0x07, 0x1c, 0x8a, 0xbc, 0x20, 0xeb, 0xce, 0x8e, 0xab, 0xee, 0x31, 0xa2,
- 0x73, 0xf9, 0xca, 0x3a, 0x1a, 0xfb, 0x0d, 0xc1, 0xfe, 0xfa, 0xf2, 0x6f, 0xbd, 0x96, 0xdd, 0x43,
- 0x52, 0xb6, 0x08, 0xf3, 0xae, 0xbe, 0x19, 0x89, 0x32, 0x26, 0xb0, 0xea, 0x4b, 0x64, 0x84, 0x82,
- 0x6b, 0xf5, 0x79, 0xbf, 0x01, 0x5f, 0x75, 0x63, 0x1b, 0x23, 0x3d, 0x68, 0x2a, 0x65, 0xe8, 0x91,
- 0xf6, 0xff, 0x13, 0x58, 0xf1, 0x47, 0x0a, 0x7f, 0xc5, 0xa7, 0xe7, 0x61, 0x5a, 0x06, 0x46, 0x44,
- 0x42, 0x04, 0xa0, 0xdb, 0x39, 0x86, 0x54, 0xaa, 0x8c, 0x34, 0x21, 0x8b, 0xf8, 0x0c, 0x74, 0x67
- },
-
- new byte[]
- {
- 0x68, 0x8d, 0xca, 0x4d, 0x73, 0x4b, 0x4e, 0x2a, 0xd4, 0x52, 0x26, 0xb3, 0x54, 0x1e, 0x19, 0x1f,
- 0x22, 0x03, 0x46, 0x3d, 0x2d, 0x4a, 0x53, 0x83, 0x13, 0x8a, 0xb7, 0xd5, 0x25, 0x79, 0xf5, 0xbd,
- 0x58, 0x2f, 0x0d, 0x02, 0xed, 0x51, 0x9e, 0x11, 0xf2, 0x3e, 0x55, 0x5e, 0xd1, 0x16, 0x3c, 0x66,
- 0x70, 0x5d, 0xf3, 0x45, 0x40, 0xcc, 0xe8, 0x94, 0x56, 0x08, 0xce, 0x1a, 0x3a, 0xd2, 0xe1, 0xdf,
- 0xb5, 0x38, 0x6e, 0x0e, 0xe5, 0xf4, 0xf9, 0x86, 0xe9, 0x4f, 0xd6, 0x85, 0x23, 0xcf, 0x32, 0x99,
- 0x31, 0x14, 0xae, 0xee, 0xc8, 0x48, 0xd3, 0x30, 0xa1, 0x92, 0x41, 0xb1, 0x18, 0xc4, 0x2c, 0x71,
- 0x72, 0x44, 0x15, 0xfd, 0x37, 0xbe, 0x5f, 0xaa, 0x9b, 0x88, 0xd8, 0xab, 0x89, 0x9c, 0xfa, 0x60,
- 0xea, 0xbc, 0x62, 0x0c, 0x24, 0xa6, 0xa8, 0xec, 0x67, 0x20, 0xdb, 0x7c, 0x28, 0xdd, 0xac, 0x5b,
- 0x34, 0x7e, 0x10, 0xf1, 0x7b, 0x8f, 0x63, 0xa0, 0x05, 0x9a, 0x43, 0x77, 0x21, 0xbf, 0x27, 0x09,
- 0xc3, 0x9f, 0xb6, 0xd7, 0x29, 0xc2, 0xeb, 0xc0, 0xa4, 0x8b, 0x8c, 0x1d, 0xfb, 0xff, 0xc1, 0xb2,
- 0x97, 0x2e, 0xf8, 0x65, 0xf6, 0x75, 0x07, 0x04, 0x49, 0x33, 0xe4, 0xd9, 0xb9, 0xd0, 0x42, 0xc7,
- 0x6c, 0x90, 0x00, 0x8e, 0x6f, 0x50, 0x01, 0xc5, 0xda, 0x47, 0x3f, 0xcd, 0x69, 0xa2, 0xe2, 0x7a,
- 0xa7, 0xc6, 0x93, 0x0f, 0x0a, 0x06, 0xe6, 0x2b, 0x96, 0xa3, 0x1c, 0xaf, 0x6a, 0x12, 0x84, 0x39,
- 0xe7, 0xb0, 0x82, 0xf7, 0xfe, 0x9d, 0x87, 0x5c, 0x81, 0x35, 0xde, 0xb4, 0xa5, 0xfc, 0x80, 0xef,
- 0xcb, 0xbb, 0x6b, 0x76, 0xba, 0x5a, 0x7d, 0x78, 0x0b, 0x95, 0xe3, 0xad, 0x74, 0x98, 0x3b, 0x36,
- 0x64, 0x6d, 0xdc, 0xf0, 0x59, 0xa9, 0x4c, 0x17, 0x7f, 0x91, 0xb8, 0xc9, 0x57, 0x1b, 0xe0, 0x61
- }
- };
-
-
- }
+ //private const ulong mdsMatrix = 0x0407060801050101UL;
+ private const ulong mdsMatrix = 0x0104070608010501UL;
+
+ private static readonly byte[][] sBoxes = new byte[][]
+ {
+ new byte[] {
+ 0xa8, 0x43, 0x5f, 0x06, 0x6b, 0x75, 0x6c, 0x59, 0x71, 0xdf, 0x87, 0x95, 0x17, 0xf0, 0xd8, 0x09,
+ 0x6d, 0xf3, 0x1d, 0xcb, 0xc9, 0x4d, 0x2c, 0xaf, 0x79, 0xe0, 0x97, 0xfd, 0x6f, 0x4b, 0x45, 0x39,
+ 0x3e, 0xdd, 0xa3, 0x4f, 0xb4, 0xb6, 0x9a, 0x0e, 0x1f, 0xbf, 0x15, 0xe1, 0x49, 0xd2, 0x93, 0xc6,
+ 0x92, 0x72, 0x9e, 0x61, 0xd1, 0x63, 0xfa, 0xee, 0xf4, 0x19, 0xd5, 0xad, 0x58, 0xa4, 0xbb, 0xa1,
+ 0xdc, 0xf2, 0x83, 0x37, 0x42, 0xe4, 0x7a, 0x32, 0x9c, 0xcc, 0xab, 0x4a, 0x8f, 0x6e, 0x04, 0x27,
+ 0x2e, 0xe7, 0xe2, 0x5a, 0x96, 0x16, 0x23, 0x2b, 0xc2, 0x65, 0x66, 0x0f, 0xbc, 0xa9, 0x47, 0x41,
+ 0x34, 0x48, 0xfc, 0xb7, 0x6a, 0x88, 0xa5, 0x53, 0x86, 0xf9, 0x5b, 0xdb, 0x38, 0x7b, 0xc3, 0x1e,
+ 0x22, 0x33, 0x24, 0x28, 0x36, 0xc7, 0xb2, 0x3b, 0x8e, 0x77, 0xba, 0xf5, 0x14, 0x9f, 0x08, 0x55,
+ 0x9b, 0x4c, 0xfe, 0x60, 0x5c, 0xda, 0x18, 0x46, 0xcd, 0x7d, 0x21, 0xb0, 0x3f, 0x1b, 0x89, 0xff,
+ 0xeb, 0x84, 0x69, 0x3a, 0x9d, 0xd7, 0xd3, 0x70, 0x67, 0x40, 0xb5, 0xde, 0x5d, 0x30, 0x91, 0xb1,
+ 0x78, 0x11, 0x01, 0xe5, 0x00, 0x68, 0x98, 0xa0, 0xc5, 0x02, 0xa6, 0x74, 0x2d, 0x0b, 0xa2, 0x76,
+ 0xb3, 0xbe, 0xce, 0xbd, 0xae, 0xe9, 0x8a, 0x31, 0x1c, 0xec, 0xf1, 0x99, 0x94, 0xaa, 0xf6, 0x26,
+ 0x2f, 0xef, 0xe8, 0x8c, 0x35, 0x03, 0xd4, 0x7f, 0xfb, 0x05, 0xc1, 0x5e, 0x90, 0x20, 0x3d, 0x82,
+ 0xf7, 0xea, 0x0a, 0x0d, 0x7e, 0xf8, 0x50, 0x1a, 0xc4, 0x07, 0x57, 0xb8, 0x3c, 0x62, 0xe3, 0xc8,
+ 0xac, 0x52, 0x64, 0x10, 0xd0, 0xd9, 0x13, 0x0c, 0x12, 0x29, 0x51, 0xb9, 0xcf, 0xd6, 0x73, 0x8d,
+ 0x81, 0x54, 0xc0, 0xed, 0x4e, 0x44, 0xa7, 0x2a, 0x85, 0x25, 0xe6, 0xca, 0x7c, 0x8b, 0x56, 0x80
+ },
+
+ new byte[] {
+ 0xce, 0xbb, 0xeb, 0x92, 0xea, 0xcb, 0x13, 0xc1, 0xe9, 0x3a, 0xd6, 0xb2, 0xd2, 0x90, 0x17, 0xf8,
+ 0x42, 0x15, 0x56, 0xb4, 0x65, 0x1c, 0x88, 0x43, 0xc5, 0x5c, 0x36, 0xba, 0xf5, 0x57, 0x67, 0x8d,
+ 0x31, 0xf6, 0x64, 0x58, 0x9e, 0xf4, 0x22, 0xaa, 0x75, 0x0f, 0x02, 0xb1, 0xdf, 0x6d, 0x73, 0x4d,
+ 0x7c, 0x26, 0x2e, 0xf7, 0x08, 0x5d, 0x44, 0x3e, 0x9f, 0x14, 0xc8, 0xae, 0x54, 0x10, 0xd8, 0xbc,
+ 0x1a, 0x6b, 0x69, 0xf3, 0xbd, 0x33, 0xab, 0xfa, 0xd1, 0x9b, 0x68, 0x4e, 0x16, 0x95, 0x91, 0xee,
+ 0x4c, 0x63, 0x8e, 0x5b, 0xcc, 0x3c, 0x19, 0xa1, 0x81, 0x49, 0x7b, 0xd9, 0x6f, 0x37, 0x60, 0xca,
+ 0xe7, 0x2b, 0x48, 0xfd, 0x96, 0x45, 0xfc, 0x41, 0x12, 0x0d, 0x79, 0xe5, 0x89, 0x8c, 0xe3, 0x20,
+ 0x30, 0xdc, 0xb7, 0x6c, 0x4a, 0xb5, 0x3f, 0x97, 0xd4, 0x62, 0x2d, 0x06, 0xa4, 0xa5, 0x83, 0x5f,
+ 0x2a, 0xda, 0xc9, 0x00, 0x7e, 0xa2, 0x55, 0xbf, 0x11, 0xd5, 0x9c, 0xcf, 0x0e, 0x0a, 0x3d, 0x51,
+ 0x7d, 0x93, 0x1b, 0xfe, 0xc4, 0x47, 0x09, 0x86, 0x0b, 0x8f, 0x9d, 0x6a, 0x07, 0xb9, 0xb0, 0x98,
+ 0x18, 0x32, 0x71, 0x4b, 0xef, 0x3b, 0x70, 0xa0, 0xe4, 0x40, 0xff, 0xc3, 0xa9, 0xe6, 0x78, 0xf9,
+ 0x8b, 0x46, 0x80, 0x1e, 0x38, 0xe1, 0xb8, 0xa8, 0xe0, 0x0c, 0x23, 0x76, 0x1d, 0x25, 0x24, 0x05,
+ 0xf1, 0x6e, 0x94, 0x28, 0x9a, 0x84, 0xe8, 0xa3, 0x4f, 0x77, 0xd3, 0x85, 0xe2, 0x52, 0xf2, 0x82,
+ 0x50, 0x7a, 0x2f, 0x74, 0x53, 0xb3, 0x61, 0xaf, 0x39, 0x35, 0xde, 0xcd, 0x1f, 0x99, 0xac, 0xad,
+ 0x72, 0x2c, 0xdd, 0xd0, 0x87, 0xbe, 0x5e, 0xa6, 0xec, 0x04, 0xc6, 0x03, 0x34, 0xfb, 0xdb, 0x59,
+ 0xb6, 0xc2, 0x01, 0xf0, 0x5a, 0xed, 0xa7, 0x66, 0x21, 0x7f, 0x8a, 0x27, 0xc7, 0xc0, 0x29, 0xd7
+ },
+
+ new byte[]{
+ 0x93, 0xd9, 0x9a, 0xb5, 0x98, 0x22, 0x45, 0xfc, 0xba, 0x6a, 0xdf, 0x02, 0x9f, 0xdc, 0x51, 0x59,
+ 0x4a, 0x17, 0x2b, 0xc2, 0x94, 0xf4, 0xbb, 0xa3, 0x62, 0xe4, 0x71, 0xd4, 0xcd, 0x70, 0x16, 0xe1,
+ 0x49, 0x3c, 0xc0, 0xd8, 0x5c, 0x9b, 0xad, 0x85, 0x53, 0xa1, 0x7a, 0xc8, 0x2d, 0xe0, 0xd1, 0x72,
+ 0xa6, 0x2c, 0xc4, 0xe3, 0x76, 0x78, 0xb7, 0xb4, 0x09, 0x3b, 0x0e, 0x41, 0x4c, 0xde, 0xb2, 0x90,
+ 0x25, 0xa5, 0xd7, 0x03, 0x11, 0x00, 0xc3, 0x2e, 0x92, 0xef, 0x4e, 0x12, 0x9d, 0x7d, 0xcb, 0x35,
+ 0x10, 0xd5, 0x4f, 0x9e, 0x4d, 0xa9, 0x55, 0xc6, 0xd0, 0x7b, 0x18, 0x97, 0xd3, 0x36, 0xe6, 0x48,
+ 0x56, 0x81, 0x8f, 0x77, 0xcc, 0x9c, 0xb9, 0xe2, 0xac, 0xb8, 0x2f, 0x15, 0xa4, 0x7c, 0xda, 0x38,
+ 0x1e, 0x0b, 0x05, 0xd6, 0x14, 0x6e, 0x6c, 0x7e, 0x66, 0xfd, 0xb1, 0xe5, 0x60, 0xaf, 0x5e, 0x33,
+ 0x87, 0xc9, 0xf0, 0x5d, 0x6d, 0x3f, 0x88, 0x8d, 0xc7, 0xf7, 0x1d, 0xe9, 0xec, 0xed, 0x80, 0x29,
+ 0x27, 0xcf, 0x99, 0xa8, 0x50, 0x0f, 0x37, 0x24, 0x28, 0x30, 0x95, 0xd2, 0x3e, 0x5b, 0x40, 0x83,
+ 0xb3, 0x69, 0x57, 0x1f, 0x07, 0x1c, 0x8a, 0xbc, 0x20, 0xeb, 0xce, 0x8e, 0xab, 0xee, 0x31, 0xa2,
+ 0x73, 0xf9, 0xca, 0x3a, 0x1a, 0xfb, 0x0d, 0xc1, 0xfe, 0xfa, 0xf2, 0x6f, 0xbd, 0x96, 0xdd, 0x43,
+ 0x52, 0xb6, 0x08, 0xf3, 0xae, 0xbe, 0x19, 0x89, 0x32, 0x26, 0xb0, 0xea, 0x4b, 0x64, 0x84, 0x82,
+ 0x6b, 0xf5, 0x79, 0xbf, 0x01, 0x5f, 0x75, 0x63, 0x1b, 0x23, 0x3d, 0x68, 0x2a, 0x65, 0xe8, 0x91,
+ 0xf6, 0xff, 0x13, 0x58, 0xf1, 0x47, 0x0a, 0x7f, 0xc5, 0xa7, 0xe7, 0x61, 0x5a, 0x06, 0x46, 0x44,
+ 0x42, 0x04, 0xa0, 0xdb, 0x39, 0x86, 0x54, 0xaa, 0x8c, 0x34, 0x21, 0x8b, 0xf8, 0x0c, 0x74, 0x67
+ },
+
+ new byte[]{
+ 0x68, 0x8d, 0xca, 0x4d, 0x73, 0x4b, 0x4e, 0x2a, 0xd4, 0x52, 0x26, 0xb3, 0x54, 0x1e, 0x19, 0x1f,
+ 0x22, 0x03, 0x46, 0x3d, 0x2d, 0x4a, 0x53, 0x83, 0x13, 0x8a, 0xb7, 0xd5, 0x25, 0x79, 0xf5, 0xbd,
+ 0x58, 0x2f, 0x0d, 0x02, 0xed, 0x51, 0x9e, 0x11, 0xf2, 0x3e, 0x55, 0x5e, 0xd1, 0x16, 0x3c, 0x66,
+ 0x70, 0x5d, 0xf3, 0x45, 0x40, 0xcc, 0xe8, 0x94, 0x56, 0x08, 0xce, 0x1a, 0x3a, 0xd2, 0xe1, 0xdf,
+ 0xb5, 0x38, 0x6e, 0x0e, 0xe5, 0xf4, 0xf9, 0x86, 0xe9, 0x4f, 0xd6, 0x85, 0x23, 0xcf, 0x32, 0x99,
+ 0x31, 0x14, 0xae, 0xee, 0xc8, 0x48, 0xd3, 0x30, 0xa1, 0x92, 0x41, 0xb1, 0x18, 0xc4, 0x2c, 0x71,
+ 0x72, 0x44, 0x15, 0xfd, 0x37, 0xbe, 0x5f, 0xaa, 0x9b, 0x88, 0xd8, 0xab, 0x89, 0x9c, 0xfa, 0x60,
+ 0xea, 0xbc, 0x62, 0x0c, 0x24, 0xa6, 0xa8, 0xec, 0x67, 0x20, 0xdb, 0x7c, 0x28, 0xdd, 0xac, 0x5b,
+ 0x34, 0x7e, 0x10, 0xf1, 0x7b, 0x8f, 0x63, 0xa0, 0x05, 0x9a, 0x43, 0x77, 0x21, 0xbf, 0x27, 0x09,
+ 0xc3, 0x9f, 0xb6, 0xd7, 0x29, 0xc2, 0xeb, 0xc0, 0xa4, 0x8b, 0x8c, 0x1d, 0xfb, 0xff, 0xc1, 0xb2,
+ 0x97, 0x2e, 0xf8, 0x65, 0xf6, 0x75, 0x07, 0x04, 0x49, 0x33, 0xe4, 0xd9, 0xb9, 0xd0, 0x42, 0xc7,
+ 0x6c, 0x90, 0x00, 0x8e, 0x6f, 0x50, 0x01, 0xc5, 0xda, 0x47, 0x3f, 0xcd, 0x69, 0xa2, 0xe2, 0x7a,
+ 0xa7, 0xc6, 0x93, 0x0f, 0x0a, 0x06, 0xe6, 0x2b, 0x96, 0xa3, 0x1c, 0xaf, 0x6a, 0x12, 0x84, 0x39,
+ 0xe7, 0xb0, 0x82, 0xf7, 0xfe, 0x9d, 0x87, 0x5c, 0x81, 0x35, 0xde, 0xb4, 0xa5, 0xfc, 0x80, 0xef,
+ 0xcb, 0xbb, 0x6b, 0x76, 0xba, 0x5a, 0x7d, 0x78, 0x0b, 0x95, 0xe3, 0xad, 0x74, 0x98, 0x3b, 0x36,
+ 0x64, 0x6d, 0xdc, 0xf0, 0x59, 0xa9, 0x4c, 0x17, 0x7f, 0x91, 0xb8, 0xc9, 0x57, 0x1b, 0xe0, 0x61
+ }
+ };
+ }
}
diff --git a/crypto/src/crypto/engines/Dstu7624Engine.cs b/crypto/src/crypto/engines/Dstu7624Engine.cs
index cdb0f50e0..534a23bbf 100644
--- a/crypto/src/crypto/engines/Dstu7624Engine.cs
+++ b/crypto/src/crypto/engines/Dstu7624Engine.cs
@@ -16,8 +16,6 @@ namespace Org.BouncyCastle.Crypto.Engines
private static readonly int BITS_IN_WORD = 64;
private static readonly int BITS_IN_BYTE = 8;
- private static readonly int REDUCTION_POLYNOMIAL = 0x011d; /* x^8 + x^4 + x^3 + x^2 + 1 */
-
private ulong[] internalState;
private ulong[] workingKey;
private ulong[][] roundKeys;
@@ -472,51 +470,55 @@ namespace Org.BouncyCastle.Crypto.Engines
MatrixMultiply(mdsInvMatrix);
}
- private void MatrixMultiply(byte[][] matrix)
+ private void MatrixMultiply(ulong matrix)
{
- int col, row, b;
- byte product;
- ulong result;
- byte[] stateBytes = Pack.UInt64_To_LE(internalState);
-
- for (col = 0; col < wordsInBlock; ++col)
+ for (int col = 0; col < wordsInBlock; ++col)
{
- result = 0;
- for (row = 8 - 1; row >= 0; --row)
+ ulong colVal = internalState[col];
+ ulong colEven = colVal & 0x00FF00FF00FF00FFUL;
+ ulong colOdd = (colVal >> 8) & 0x00FF00FF00FF00FFUL;
+
+ //ulong rowMatrix = (matrix >> 8) | (matrix << 56);
+ ulong rowMatrix = matrix;
+
+ ulong result = 0;
+ for (int row = 7; row >= 0; --row)
{
- product = 0;
- for (b = 8 - 1; b >= 0; --b)
- {
- product ^= MultiplyGF(stateBytes[b + col * 8], matrix[row][b]);
- }
- result |= (ulong)product << (row * 8);
+ ulong product = MultiplyGFx4(colEven, rowMatrix & 0x00FF00FF00FF00FFUL);
+
+ rowMatrix = (rowMatrix >> 8) | (rowMatrix << 56);
+
+ product ^= MultiplyGFx4(colOdd, rowMatrix & 0x00FF00FF00FF00FFUL);
+
+ product ^= (product >> 32);
+ product ^= (product >> 16);
+
+ result <<= 8;
+ result |= (product & 0xFFUL);
}
+
internalState[col] = result;
}
}
- private byte MultiplyGF(byte x, byte y)
+ /* Pair-wise GF multiplication of 4 byte-pairs (at bits 0, 16, 32, 48 within x, y) */
+ private static ulong MultiplyGFx4(ulong u, ulong v)
{
- byte r = 0;
- byte hbit = 0;
+ ulong r = u & ((v & 0x0001000100010001UL) * 0xFFFFUL);
- for (int i = 0; i < BITS_IN_BYTE; i++)
+ for (int i = 1; i < 8; ++i)
{
- if ((y & 0x01) == 1)
- {
- r ^= x;
- }
-
- hbit = (byte)(x & 0x80);
+ u <<= 1;
+ v >>= 1;
+ r ^= u & ((v & 0x0001000100010001L) * 0xFFFFL);
+ }
- x <<= 1;
+ // REDUCTION_POLYNOMIAL = 0x011d; /* x^8 + x^4 + x^3 + x^2 + 1 */
- if (hbit == 0x80)
- {
- x = (byte)((int)x ^ REDUCTION_POLYNOMIAL);
- }
- y >>= 1;
- }
+ ulong hi = r & 0xFF00FF00FF00FF00UL;
+ r ^= hi ^ (hi >> 4) ^ (hi >> 5) ^ (hi >> 6) ^ (hi >> 8);
+ hi = r & 0x0F000F000F000F00UL;
+ r ^= hi ^ (hi >> 4) ^ (hi >> 5) ^ (hi >> 6) ^ (hi >> 8);
return r;
}
@@ -552,29 +554,10 @@ namespace Org.BouncyCastle.Crypto.Engines
#region TABLES AND S-BOXES
- private byte[][] mdsMatrix =
- {
- new byte[] { 0x01, 0x01, 0x05, 0x01, 0x08, 0x06, 0x07, 0x04 },
- new byte[] { 0x04, 0x01, 0x01, 0x05, 0x01, 0x08, 0x06, 0x07 },
- new byte[] { 0x07, 0x04, 0x01, 0x01, 0x05, 0x01, 0x08, 0x06 },
- new byte[] { 0x06, 0x07, 0x04, 0x01, 0x01, 0x05, 0x01, 0x08 },
- new byte[] { 0x08, 0x06, 0x07, 0x04, 0x01, 0x01, 0x05, 0x01 },
- new byte[] { 0x01, 0x08, 0x06, 0x07, 0x04, 0x01, 0x01, 0x05 },
- new byte[] { 0x05, 0x01, 0x08, 0x06, 0x07, 0x04, 0x01, 0x01 },
- new byte[] { 0x01, 0x05, 0x01, 0x08, 0x06, 0x07, 0x04, 0x01 },
- };
-
- private byte[][] mdsInvMatrix =
- {
- new byte[] { 0xAD, 0x95, 0x76, 0xA8, 0x2F, 0x49, 0xD7, 0xCA },
- new byte[] { 0xCA, 0xAD, 0x95, 0x76, 0xA8, 0x2F, 0x49, 0xD7 },
- new byte[] { 0xD7, 0xCA, 0xAD, 0x95, 0x76, 0xA8, 0x2F, 0x49 },
- new byte[] { 0x49, 0xD7, 0xCA, 0xAD, 0x95, 0x76, 0xA8, 0x2F },
- new byte[] { 0x2F, 0x49, 0xD7, 0xCA, 0xAD, 0x95, 0x76, 0xA8 },
- new byte[] { 0xA8, 0x2F, 0x49, 0xD7, 0xCA, 0xAD, 0x95, 0x76 },
- new byte[] { 0x76, 0xA8, 0x2F, 0x49, 0xD7, 0xCA, 0xAD, 0x95 },
- new byte[] { 0x95, 0x76, 0xA8, 0x2F, 0x49, 0xD7, 0xCA, 0xAD },
- };
+ //private const ulong mdsMatrix = 0x0407060801050101UL;
+ //private const ulong mdsInvMatrix = 0xCAD7492FA87695ADUL;
+ private const ulong mdsMatrix = 0x0104070608010501UL;
+ private const ulong mdsInvMatrix = 0xADCAD7492FA87695UL;
private byte[][] sboxesForEncryption =
{
diff --git a/crypto/src/crypto/engines/SM2Engine.cs b/crypto/src/crypto/engines/SM2Engine.cs
new file mode 100644
index 000000000..e5f12bbbb
--- /dev/null
+++ b/crypto/src/crypto/engines/SM2Engine.cs
@@ -0,0 +1,238 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Math.EC.Multiplier;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+ /// <summary>
+ /// SM2 public key encryption engine - based on https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02.
+ /// </summary>
+ public class SM2Engine
+ {
+ private readonly IDigest mDigest;
+
+ private bool mForEncryption;
+ private ECKeyParameters mECKey;
+ private ECDomainParameters mECParams;
+ private int mCurveLength;
+ private SecureRandom mRandom;
+
+ public SM2Engine()
+ : this(new SM3Digest())
+ {
+ }
+
+ public SM2Engine(IDigest digest)
+ {
+ this.mDigest = digest;
+ }
+
+ public virtual void Init(bool forEncryption, ICipherParameters param)
+ {
+ this.mForEncryption = forEncryption;
+
+ if (forEncryption)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ mECKey = (ECKeyParameters)rParam.Parameters;
+ mECParams = mECKey.Parameters;
+
+ ECPoint s = ((ECPublicKeyParameters)mECKey).Q.Multiply(mECParams.H);
+ if (s.IsInfinity)
+ throw new ArgumentException("invalid key: [h]Q at infinity");
+
+ mRandom = rParam.Random;
+ }
+ else
+ {
+ mECKey = (ECKeyParameters)param;
+ mECParams = mECKey.Parameters;
+ }
+
+ mCurveLength = (mECParams.Curve.FieldSize + 7) / 8;
+ }
+
+ public virtual byte[] ProcessBlock(byte[] input, int inOff, int inLen)
+ {
+ if (mForEncryption)
+ {
+ return Encrypt(input, inOff, inLen);
+ }
+ else
+ {
+ return Decrypt(input, inOff, inLen);
+ }
+ }
+
+ protected virtual ECMultiplier CreateBasePointMultiplier()
+ {
+ return new FixedPointCombMultiplier();
+ }
+
+ private byte[] Encrypt(byte[] input, int inOff, int inLen)
+ {
+ byte[] c2 = new byte[inLen];
+
+ Array.Copy(input, inOff, c2, 0, c2.Length);
+
+ ECMultiplier multiplier = CreateBasePointMultiplier();
+
+ byte[] c1;
+ ECPoint kPB;
+ do
+ {
+ BigInteger k = NextK();
+
+ ECPoint c1P = multiplier.Multiply(mECParams.G, k).Normalize();
+
+ c1 = c1P.GetEncoded(false);
+
+ kPB = ((ECPublicKeyParameters)mECKey).Q.Multiply(k).Normalize();
+
+ Kdf(mDigest, kPB, c2);
+ }
+ while (NotEncrypted(c2, input, inOff));
+
+ AddFieldElement(mDigest, kPB.AffineXCoord);
+ mDigest.BlockUpdate(input, inOff, inLen);
+ AddFieldElement(mDigest, kPB.AffineYCoord);
+
+ byte[] c3 = DigestUtilities.DoFinal(mDigest);
+
+ return Arrays.ConcatenateAll(c1, c2, c3);
+ }
+
+ private byte[] Decrypt(byte[] input, int inOff, int inLen)
+ {
+ byte[] c1 = new byte[mCurveLength * 2 + 1];
+
+ Array.Copy(input, inOff, c1, 0, c1.Length);
+
+ ECPoint c1P = mECParams.Curve.DecodePoint(c1);
+
+ ECPoint s = c1P.Multiply(mECParams.H);
+ if (s.IsInfinity)
+ throw new InvalidCipherTextException("[h]C1 at infinity");
+
+ c1P = c1P.Multiply(((ECPrivateKeyParameters)mECKey).D).Normalize();
+
+ byte[] c2 = new byte[inLen - c1.Length - mDigest.GetDigestSize()];
+
+ Array.Copy(input, inOff + c1.Length, c2, 0, c2.Length);
+
+ Kdf(mDigest, c1P, c2);
+
+ AddFieldElement(mDigest, c1P.AffineXCoord);
+ mDigest.BlockUpdate(c2, 0, c2.Length);
+ AddFieldElement(mDigest, c1P.AffineYCoord);
+
+ byte[] c3 = DigestUtilities.DoFinal(mDigest);
+
+ int check = 0;
+ for (int i = 0; i != c3.Length; i++)
+ {
+ check |= c3[i] ^ input[c1.Length + c2.Length + i];
+ }
+
+ Arrays.Fill(c1, 0);
+ Arrays.Fill(c3, 0);
+
+ if (check != 0)
+ {
+ Arrays.Fill(c2, 0);
+ throw new InvalidCipherTextException("invalid cipher text");
+ }
+
+ return c2;
+ }
+
+ private bool NotEncrypted(byte[] encData, byte[] input, int inOff)
+ {
+ for (int i = 0; i != encData.Length; i++)
+ {
+ if (encData[i] != input[inOff])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private void Kdf(IDigest digest, ECPoint c1, byte[] encData)
+ {
+ int digestSize = digest.GetDigestSize();
+ byte[] buf = new byte[System.Math.Max(4, digestSize)];
+ int off = 0;
+
+ IMemoable memo = digest as IMemoable;
+ IMemoable copy = null;
+
+ if (memo != null)
+ {
+ AddFieldElement(digest, c1.AffineXCoord);
+ AddFieldElement(digest, c1.AffineYCoord);
+ copy = memo.Copy();
+ }
+
+ uint ct = 0;
+
+ while (off < encData.Length)
+ {
+ if (memo != null)
+ {
+ memo.Reset(copy);
+ }
+ else
+ {
+ AddFieldElement(digest, c1.AffineXCoord);
+ AddFieldElement(digest, c1.AffineYCoord);
+ }
+
+ Pack.UInt32_To_BE(++ct, buf, 0);
+ digest.BlockUpdate(buf, 0, 4);
+ digest.DoFinal(buf, 0);
+
+ int xorLen = System.Math.Min(digestSize, encData.Length - off);
+ Xor(encData, buf, off, xorLen);
+ off += xorLen;
+ }
+ }
+
+ private void Xor(byte[] data, byte[] kdfOut, int dOff, int dRemaining)
+ {
+ for (int i = 0; i != dRemaining; i++)
+ {
+ data[dOff + i] ^= kdfOut[i];
+ }
+ }
+
+ private BigInteger NextK()
+ {
+ int qBitLength = mECParams.N.BitLength;
+
+ BigInteger k;
+ do
+ {
+ k = new BigInteger(qBitLength, mRandom);
+ }
+ while (k.SignValue == 0 || k.CompareTo(mECParams.N) >= 0);
+
+ return k;
+ }
+
+ private void AddFieldElement(IDigest digest, ECFieldElement v)
+ {
+ byte[] p = v.GetEncoded();
+ digest.BlockUpdate(p, 0, p.Length);
+ }
+ }
+}
diff --git a/crypto/src/crypto/generators/HKDFBytesGenerator.cs b/crypto/src/crypto/generators/HKDFBytesGenerator.cs
index c2e667c95..6f36a6faa 100644
--- a/crypto/src/crypto/generators/HKDFBytesGenerator.cs
+++ b/crypto/src/crypto/generators/HKDFBytesGenerator.cs
@@ -66,7 +66,6 @@ namespace Org.BouncyCastle.Crypto.Generators
*/
private KeyParameter Extract(byte[] salt, byte[] ikm)
{
- hMacHash.Init(new KeyParameter(ikm));
if (salt == null)
{
// TODO check if hashLen is indeed same as HMAC size
diff --git a/crypto/src/crypto/parameters/ParametersWithID.cs b/crypto/src/crypto/parameters/ParametersWithID.cs
new file mode 100644
index 000000000..37f68705b
--- /dev/null
+++ b/crypto/src/crypto/parameters/ParametersWithID.cs
@@ -0,0 +1,36 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+ public class ParametersWithID
+ : ICipherParameters
+ {
+ private readonly ICipherParameters parameters;
+ private readonly byte[] id;
+
+ public ParametersWithID(ICipherParameters parameters,
+ byte[] id)
+ : this(parameters, id, 0, id.Length)
+ {
+ }
+
+ public ParametersWithID(ICipherParameters parameters,
+ byte[] id, int idOff, int idLen)
+ {
+ this.parameters = parameters;
+ this.id = Arrays.CopyOfRange(id, idOff, idOff + idLen);
+ }
+
+ public byte[] GetID()
+ {
+ return id;
+ }
+
+ public ICipherParameters Parameters
+ {
+ get { return parameters; }
+ }
+ }
+}
diff --git a/crypto/src/crypto/parameters/ParametersWithIV.cs b/crypto/src/crypto/parameters/ParametersWithIV.cs
index 11a8b77a0..4b2eb930f 100644
--- a/crypto/src/crypto/parameters/ParametersWithIV.cs
+++ b/crypto/src/crypto/parameters/ParametersWithIV.cs
@@ -1,41 +1,38 @@
using System;
+using Org.BouncyCastle.Utilities;
+
namespace Org.BouncyCastle.Crypto.Parameters
{
public class ParametersWithIV
- : ICipherParameters
+ : ICipherParameters
{
- private readonly ICipherParameters parameters;
- private readonly byte[] iv;
+ private readonly ICipherParameters parameters;
+ private readonly byte[] iv;
- public ParametersWithIV(
- ICipherParameters parameters,
- byte[] iv)
- : this(parameters, iv, 0, iv.Length)
- {
- }
+ public ParametersWithIV(ICipherParameters parameters,
+ byte[] iv)
+ : this(parameters, iv, 0, iv.Length)
+ {
+ }
- public ParametersWithIV(
- ICipherParameters parameters,
- byte[] iv,
- int ivOff,
- int ivLen)
+ public ParametersWithIV(ICipherParameters parameters,
+ byte[] iv, int ivOff, int ivLen)
{
// NOTE: 'parameters' may be null to imply key re-use
- if (iv == null)
- throw new ArgumentNullException("iv");
+ if (iv == null)
+ throw new ArgumentNullException("iv");
- this.parameters = parameters;
- this.iv = new byte[ivLen];
- Array.Copy(iv, ivOff, this.iv, 0, ivLen);
+ this.parameters = parameters;
+ this.iv = Arrays.CopyOfRange(iv, ivOff, ivOff + ivLen);
}
- public byte[] GetIV()
+ public byte[] GetIV()
{
- return (byte[]) iv.Clone();
+ return (byte[])iv.Clone();
}
- public ICipherParameters Parameters
+ public ICipherParameters Parameters
{
get { return parameters; }
}
diff --git a/crypto/src/crypto/parameters/SM2KeyExchangePrivateParameters.cs b/crypto/src/crypto/parameters/SM2KeyExchangePrivateParameters.cs
new file mode 100644
index 000000000..8afb61544
--- /dev/null
+++ b/crypto/src/crypto/parameters/SM2KeyExchangePrivateParameters.cs
@@ -0,0 +1,64 @@
+using System;
+
+using Org.BouncyCastle.Math.EC;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+ /// <summary>Private parameters for an SM2 key exchange.</summary>
+ /// <remarks>The ephemeralPrivateKey is used to calculate the random point used in the algorithm.</remarks>
+ public class SM2KeyExchangePrivateParameters
+ : ICipherParameters
+ {
+ private readonly bool mInitiator;
+ private readonly ECPrivateKeyParameters mStaticPrivateKey;
+ private readonly ECPoint mStaticPublicPoint;
+ private readonly ECPrivateKeyParameters mEphemeralPrivateKey;
+ private readonly ECPoint mEphemeralPublicPoint;
+
+ public SM2KeyExchangePrivateParameters(
+ bool initiator,
+ ECPrivateKeyParameters staticPrivateKey,
+ ECPrivateKeyParameters ephemeralPrivateKey)
+ {
+ if (staticPrivateKey == null)
+ throw new ArgumentNullException("staticPrivateKey");
+ if (ephemeralPrivateKey == null)
+ throw new ArgumentNullException("ephemeralPrivateKey");
+
+ ECDomainParameters parameters = staticPrivateKey.Parameters;
+ if (!parameters.Equals(ephemeralPrivateKey.Parameters))
+ throw new ArgumentException("Static and ephemeral private keys have different domain parameters");
+
+ this.mInitiator = initiator;
+ this.mStaticPrivateKey = staticPrivateKey;
+ this.mStaticPublicPoint = parameters.G.Multiply(staticPrivateKey.D).Normalize();
+ this.mEphemeralPrivateKey = ephemeralPrivateKey;
+ this.mEphemeralPublicPoint = parameters.G.Multiply(ephemeralPrivateKey.D).Normalize();
+ }
+
+ public virtual bool IsInitiator
+ {
+ get { return mInitiator; }
+ }
+
+ public virtual ECPrivateKeyParameters StaticPrivateKey
+ {
+ get { return mStaticPrivateKey; }
+ }
+
+ public virtual ECPoint StaticPublicPoint
+ {
+ get { return mStaticPublicPoint; }
+ }
+
+ public virtual ECPrivateKeyParameters EphemeralPrivateKey
+ {
+ get { return mEphemeralPrivateKey; }
+ }
+
+ public virtual ECPoint EphemeralPublicPoint
+ {
+ get { return mEphemeralPublicPoint; }
+ }
+ }
+}
diff --git a/crypto/src/crypto/parameters/SM2KeyExchangePublicParameters.cs b/crypto/src/crypto/parameters/SM2KeyExchangePublicParameters.cs
new file mode 100644
index 000000000..5c213159e
--- /dev/null
+++ b/crypto/src/crypto/parameters/SM2KeyExchangePublicParameters.cs
@@ -0,0 +1,40 @@
+using System;
+
+using Org.BouncyCastle.Math.EC;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+ /// <summary>Public parameters for an SM2 key exchange.</summary>
+ /// <remarks>In this case the ephemeralPublicKey provides the random point used in the algorithm.</remarks>
+ public class SM2KeyExchangePublicParameters
+ : ICipherParameters
+ {
+ private readonly ECPublicKeyParameters mStaticPublicKey;
+ private readonly ECPublicKeyParameters mEphemeralPublicKey;
+
+ public SM2KeyExchangePublicParameters(
+ ECPublicKeyParameters staticPublicKey,
+ ECPublicKeyParameters ephemeralPublicKey)
+ {
+ if (staticPublicKey == null)
+ throw new ArgumentNullException("staticPublicKey");
+ if (ephemeralPublicKey == null)
+ throw new ArgumentNullException("ephemeralPublicKey");
+ if (!staticPublicKey.Parameters.Equals(ephemeralPublicKey.Parameters))
+ throw new ArgumentException("Static and ephemeral public keys have different domain parameters");
+
+ this.mStaticPublicKey = staticPublicKey;
+ this.mEphemeralPublicKey = ephemeralPublicKey;
+ }
+
+ public virtual ECPublicKeyParameters StaticPublicKey
+ {
+ get { return mStaticPublicKey; }
+ }
+
+ public virtual ECPublicKeyParameters EphemeralPublicKey
+ {
+ get { return mEphemeralPublicKey; }
+ }
+ }
+}
diff --git a/crypto/src/crypto/prng/CryptoApiEntropySourceProvider.cs b/crypto/src/crypto/prng/CryptoApiEntropySourceProvider.cs
index 68579aaf4..459d3a740 100644
--- a/crypto/src/crypto/prng/CryptoApiEntropySourceProvider.cs
+++ b/crypto/src/crypto/prng/CryptoApiEntropySourceProvider.cs
@@ -11,7 +11,7 @@ namespace Org.BouncyCastle.Crypto.Prng
private readonly bool mPredictionResistant;
public CryptoApiEntropySourceProvider()
- : this(new RNGCryptoServiceProvider(), true)
+ : this(RandomNumberGenerator.Create(), true)
{
}
diff --git a/crypto/src/crypto/prng/CryptoApiRandomGenerator.cs b/crypto/src/crypto/prng/CryptoApiRandomGenerator.cs
index fa5f523d3..0b6592025 100644
--- a/crypto/src/crypto/prng/CryptoApiRandomGenerator.cs
+++ b/crypto/src/crypto/prng/CryptoApiRandomGenerator.cs
@@ -6,7 +6,7 @@ using System.Security.Cryptography;
namespace Org.BouncyCastle.Crypto.Prng
{
/// <summary>
- /// Uses Microsoft's RNGCryptoServiceProvider
+ /// Uses RandomNumberGenerator.Create() to get randomness generator
/// </summary>
public class CryptoApiRandomGenerator
: IRandomGenerator
@@ -14,7 +14,7 @@ namespace Org.BouncyCastle.Crypto.Prng
private readonly RandomNumberGenerator rndProv;
public CryptoApiRandomGenerator()
- : this(new RNGCryptoServiceProvider())
+ : this(RandomNumberGenerator.Create())
{
}
diff --git a/crypto/src/crypto/signers/SM2Signer.cs b/crypto/src/crypto/signers/SM2Signer.cs
new file mode 100644
index 000000000..8151e6be0
--- /dev/null
+++ b/crypto/src/crypto/signers/SM2Signer.cs
@@ -0,0 +1,258 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Math.EC.Multiplier;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Crypto.Signers
+{
+ /// <summary>The SM2 Digital Signature algorithm.</summary>
+ public class SM2Signer
+ : ISigner
+ {
+ private readonly IDsaKCalculator kCalculator = new RandomDsaKCalculator();
+ private readonly SM3Digest digest = new SM3Digest();
+
+ private ECDomainParameters ecParams;
+ private ECPoint pubPoint;
+ private ECKeyParameters ecKey;
+ private byte[] z;
+
+ public virtual string AlgorithmName
+ {
+ get { return "SM2Sign"; }
+ }
+
+ public virtual void Init(bool forSigning, ICipherParameters parameters)
+ {
+ ICipherParameters baseParam;
+ byte[] userID;
+
+ if (parameters is ParametersWithID)
+ {
+ baseParam = ((ParametersWithID)parameters).Parameters;
+ userID = ((ParametersWithID)parameters).GetID();
+ }
+ else
+ {
+ baseParam = parameters;
+ userID = Hex.Decode("31323334353637383132333435363738"); // the default value (ASCII "1234567812345678")
+ }
+
+ if (forSigning)
+ {
+ if (baseParam is ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)baseParam;
+
+ ecKey = (ECKeyParameters)rParam.Parameters;
+ ecParams = ecKey.Parameters;
+ kCalculator.Init(ecParams.N, rParam.Random);
+ }
+ else
+ {
+ ecKey = (ECKeyParameters)baseParam;
+ ecParams = ecKey.Parameters;
+ kCalculator.Init(ecParams.N, new SecureRandom());
+ }
+ pubPoint = CreateBasePointMultiplier().Multiply(ecParams.G, ((ECPrivateKeyParameters)ecKey).D).Normalize();
+ }
+ else
+ {
+ ecKey = (ECKeyParameters)baseParam;
+ ecParams = ecKey.Parameters;
+ pubPoint = ((ECPublicKeyParameters)ecKey).Q;
+ }
+
+ digest.Reset();
+ z = GetZ(userID);
+
+ digest.BlockUpdate(z, 0, z.Length);
+ }
+
+ public virtual void Update(byte b)
+ {
+ digest.Update(b);
+ }
+
+ public virtual void BlockUpdate(byte[] buf, int off, int len)
+ {
+ digest.BlockUpdate(buf, off, len);
+ }
+
+ public virtual bool VerifySignature(byte[] signature)
+ {
+ try
+ {
+ BigInteger[] rs = DerDecode(signature);
+ if (rs != null)
+ {
+ return VerifySignature(rs[0], rs[1]);
+ }
+ }
+ catch (IOException e)
+ {
+ }
+
+ return false;
+ }
+
+ public virtual void Reset()
+ {
+ if (z != null)
+ {
+ digest.Reset();
+ digest.BlockUpdate(z, 0, z.Length);
+ }
+ }
+
+ public virtual byte[] GenerateSignature()
+ {
+ byte[] eHash = DigestUtilities.DoFinal(digest);
+
+ BigInteger n = ecParams.N;
+ BigInteger e = CalculateE(eHash);
+ BigInteger d = ((ECPrivateKeyParameters)ecKey).D;
+
+ BigInteger r, s;
+
+ ECMultiplier basePointMultiplier = CreateBasePointMultiplier();
+
+ // 5.2.1 Draft RFC: SM2 Public Key Algorithms
+ do // generate s
+ {
+ BigInteger k;
+ do // generate r
+ {
+ // A3
+ k = kCalculator.NextK();
+
+ // A4
+ ECPoint p = basePointMultiplier.Multiply(ecParams.G, k).Normalize();
+
+ // A5
+ r = e.Add(p.AffineXCoord.ToBigInteger()).Mod(n);
+ }
+ while (r.SignValue == 0 || r.Add(k).Equals(n));
+
+ // A6
+ BigInteger dPlus1ModN = d.Add(BigInteger.One).ModInverse(n);
+
+ s = k.Subtract(r.Multiply(d)).Mod(n);
+ s = dPlus1ModN.Multiply(s).Mod(n);
+ }
+ while (s.SignValue == 0);
+
+ // A7
+ try
+ {
+ return DerEncode(r, s);
+ }
+ catch (IOException ex)
+ {
+ throw new CryptoException("unable to encode signature: " + ex.Message, ex);
+ }
+ }
+
+ private bool VerifySignature(BigInteger r, BigInteger s)
+ {
+ BigInteger n = ecParams.N;
+
+ // 5.3.1 Draft RFC: SM2 Public Key Algorithms
+ // B1
+ if (r.CompareTo(BigInteger.One) < 0 || r.CompareTo(n) >= 0)
+ return false;
+
+ // B2
+ if (s.CompareTo(BigInteger.One) < 0 || s.CompareTo(n) >= 0)
+ return false;
+
+ // B3
+ byte[] eHash = DigestUtilities.DoFinal(digest);
+
+ // B4
+ BigInteger e = CalculateE(eHash);
+
+ // B5
+ BigInteger t = r.Add(s).Mod(n);
+ if (t.SignValue == 0)
+ return false;
+
+ // B6
+ ECPoint q = ((ECPublicKeyParameters)ecKey).Q;
+ ECPoint x1y1 = ECAlgorithms.SumOfTwoMultiplies(ecParams.G, s, q, t).Normalize();
+ if (x1y1.IsInfinity)
+ return false;
+
+ // B7
+ return r.Equals(e.Add(x1y1.AffineXCoord.ToBigInteger()).Mod(n));
+ }
+
+ private byte[] GetZ(byte[] userID)
+ {
+ AddUserID(digest, userID);
+
+ AddFieldElement(digest, ecParams.Curve.A);
+ AddFieldElement(digest, ecParams.Curve.B);
+ AddFieldElement(digest, ecParams.G.AffineXCoord);
+ AddFieldElement(digest, ecParams.G.AffineYCoord);
+ AddFieldElement(digest, pubPoint.AffineXCoord);
+ AddFieldElement(digest, pubPoint.AffineYCoord);
+
+ return DigestUtilities.DoFinal(digest);
+ }
+
+ private void AddUserID(IDigest digest, byte[] userID)
+ {
+ int len = userID.Length * 8;
+ digest.Update((byte)(len >> 8));
+ digest.Update((byte)len);
+ digest.BlockUpdate(userID, 0, userID.Length);
+ }
+
+ private void AddFieldElement(IDigest digest, ECFieldElement v)
+ {
+ byte[] p = v.GetEncoded();
+ digest.BlockUpdate(p, 0, p.Length);
+ }
+
+ protected virtual BigInteger CalculateE(byte[] message)
+ {
+ return new BigInteger(1, message);
+ }
+
+ protected virtual ECMultiplier CreateBasePointMultiplier()
+ {
+ return new FixedPointCombMultiplier();
+ }
+
+ protected virtual BigInteger[] DerDecode(byte[] encoding)
+ {
+ Asn1Sequence seq = Asn1Sequence.GetInstance(Asn1Object.FromByteArray(encoding));
+ if (seq.Count != 2)
+ return null;
+
+ BigInteger r = DerInteger.GetInstance(seq[0]).Value;
+ BigInteger s = DerInteger.GetInstance(seq[1]).Value;
+
+ byte[] expectedEncoding = DerEncode(r, s);
+ if (!Arrays.ConstantTimeAreEqual(expectedEncoding, encoding))
+ return null;
+
+ return new BigInteger[]{ r, s };
+ }
+
+ protected virtual byte[] DerEncode(BigInteger r, BigInteger s)
+ {
+ return new DerSequence(new DerInteger(r), new DerInteger(s)).GetEncoded(Asn1Encodable.Der);
+ }
+ }
+}
diff --git a/crypto/src/crypto/tls/CertificateStatus.cs b/crypto/src/crypto/tls/CertificateStatus.cs
index 0f95475b9..bc4128722 100644
--- a/crypto/src/crypto/tls/CertificateStatus.cs
+++ b/crypto/src/crypto/tls/CertificateStatus.cs
@@ -95,7 +95,7 @@ namespace Org.BouncyCastle.Crypto.Tls
case CertificateStatusType.ocsp:
return response is OcspResponse;
default:
- throw new ArgumentException("unsupported value", "statusType");
+ throw new ArgumentException("unsupported CertificateStatusType", "statusType");
}
}
}
diff --git a/crypto/src/crypto/tls/CertificateStatusRequest.cs b/crypto/src/crypto/tls/CertificateStatusRequest.cs
index 9587d7df8..24ce37655 100644
--- a/crypto/src/crypto/tls/CertificateStatusRequest.cs
+++ b/crypto/src/crypto/tls/CertificateStatusRequest.cs
@@ -88,7 +88,7 @@ namespace Org.BouncyCastle.Crypto.Tls
case CertificateStatusType.ocsp:
return request is OcspStatusRequest;
default:
- throw new ArgumentException("unsupported value", "statusType");
+ throw new ArgumentException("unsupported CertificateStatusType", "statusType");
}
}
}
diff --git a/crypto/src/crypto/tls/ServerName.cs b/crypto/src/crypto/tls/ServerName.cs
index 508c2ddbc..45d18b79b 100644
--- a/crypto/src/crypto/tls/ServerName.cs
+++ b/crypto/src/crypto/tls/ServerName.cs
@@ -98,7 +98,7 @@ namespace Org.BouncyCastle.Crypto.Tls
case Tls.NameType.host_name:
return name is string;
default:
- throw new ArgumentException("unsupported value", "name");
+ throw new ArgumentException("unsupported NameType", "nameType");
}
}
}
diff --git a/crypto/src/math/ec/multiplier/FixedPointCombMultiplier.cs b/crypto/src/math/ec/multiplier/FixedPointCombMultiplier.cs
index a8ef5a77a..05bb4000b 100644
--- a/crypto/src/math/ec/multiplier/FixedPointCombMultiplier.cs
+++ b/crypto/src/math/ec/multiplier/FixedPointCombMultiplier.cs
@@ -48,7 +48,7 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
R = R.TwicePlus(lookupTable[index]);
}
- return R;
+ return R.Add(info.Offset);
}
protected virtual int GetWidthForCombSize(int combSize)
diff --git a/crypto/src/math/ec/multiplier/FixedPointPreCompInfo.cs b/crypto/src/math/ec/multiplier/FixedPointPreCompInfo.cs
index 56a6326a1..11bdadc6f 100644
--- a/crypto/src/math/ec/multiplier/FixedPointPreCompInfo.cs
+++ b/crypto/src/math/ec/multiplier/FixedPointPreCompInfo.cs
@@ -6,11 +6,13 @@
public class FixedPointPreCompInfo
: PreCompInfo
{
+ protected ECPoint m_offset = null;
+
/**
* Array holding the precomputed <code>ECPoint</code>s used for a fixed
* point multiplication.
*/
- protected ECPoint[] m_preComp = null;
+ protected ECPoint[] m_preComp = null;
/**
* The width used for the precomputation. If a larger width precomputation
@@ -19,6 +21,12 @@
*/
protected int m_width = -1;
+ public virtual ECPoint Offset
+ {
+ get { return m_offset; }
+ set { this.m_offset = value; }
+ }
+
public virtual ECPoint[] PreComp
{
get { return m_preComp; }
diff --git a/crypto/src/math/ec/multiplier/FixedPointUtilities.cs b/crypto/src/math/ec/multiplier/FixedPointUtilities.cs
index d927d010b..8e129a8f3 100644
--- a/crypto/src/math/ec/multiplier/FixedPointUtilities.cs
+++ b/crypto/src/math/ec/multiplier/FixedPointUtilities.cs
@@ -35,17 +35,20 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
int bits = GetCombSize(c);
int d = (bits + minWidth - 1) / minWidth;
- ECPoint[] pow2Table = new ECPoint[minWidth];
+ ECPoint[] pow2Table = new ECPoint[minWidth + 1];
pow2Table[0] = p;
for (int i = 1; i < minWidth; ++i)
{
pow2Table[i] = pow2Table[i - 1].TimesPow2(d);
}
-
+
+ // This will be the 'offset' value
+ pow2Table[minWidth] = pow2Table[0].Subtract(pow2Table[1]);
+
c.NormalizeAll(pow2Table);
lookupTable = new ECPoint[n];
- lookupTable[0] = c.Infinity;
+ lookupTable[0] = pow2Table[0];
for (int bit = minWidth - 1; bit >= 0; --bit)
{
@@ -60,6 +63,7 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
c.NormalizeAll(lookupTable);
+ info.Offset = pow2Table[minWidth];
info.PreComp = lookupTable;
info.Width = minWidth;
diff --git a/crypto/src/util/encoders/Base64Encoder.cs b/crypto/src/util/encoders/Base64Encoder.cs
index 7b53df25a..07294c9a6 100644
--- a/crypto/src/util/encoders/Base64Encoder.cs
+++ b/crypto/src/util/encoders/Base64Encoder.cs
@@ -269,6 +269,9 @@ namespace Org.BouncyCastle.Utilities.Encoders
{
if (c3 == padding)
{
+ if (c4 != padding)
+ throw new IOException("invalid characters encountered at end of base64 data");
+
byte b1 = decodingTable[c1];
byte b2 = decodingTable[c2];
diff --git a/crypto/test/data/ThawteSGCCA.cer b/crypto/test/data/ThawteSGCCA.cer
new file mode 100644
index 000000000..14dfab308
--- /dev/null
+++ b/crypto/test/data/ThawteSGCCA.cer
Binary files differdiff --git a/crypto/test/data/ThawteSGCCA.crl b/crypto/test/data/ThawteSGCCA.crl
new file mode 100644
index 000000000..06628261a
--- /dev/null
+++ b/crypto/test/data/ThawteSGCCA.crl
Binary files differdiff --git a/crypto/test/data/cert_chain.data b/crypto/test/data/cert_chain.data
new file mode 100644
index 000000000..00b56dd74
--- /dev/null
+++ b/crypto/test/data/cert_chain.data
@@ -0,0 +1,60 @@
+-----BEGIN CERTIFICATE-----
+MIIE+TCCAuGgAwIBAgIVAIb1Te5/365tZJu71WN94Kh2FpSoMA0GCSqGSIb3DQEB
+DQUAMBUxEzARBgNVBAsTClJvb3QgVEUgQ0EwHhcNMTUwNzAyMTU1MDA4WhcNMzUw
+NzA3MTU1MDA4WjAvMRQwEgYDVQQDEwsxMC4yMTEuNTUuMzEXMBUGA1UECxMOVEUg
+Uk1JIEhvc3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCU85zq
+Kwn80yW/QZjafyTnDiaPOr8X5u8OwTe+dbQPK2xSdT7d6FqEM8rmY9njGhue5XLH
+xKcUweVMt6E9h581qMrf39sldWMyoHxZiquPfs0t3zfMa3hYF5AONH5I3zdTZQj4
++5SD0mJugeM7YQ6eRs8qBdKLN/FwRWRAWQwDe3gF1gW5mgXfuo4Z3ufVscbJziJr
+L9gnYaqCfmI8MaDWeDNkB9biTYPXGh0oacUSpWUHyyrTlzodaKhd+m5FAgDUFlV4
+I9iv7YO4DT9sJmxmNFMrTN+c5HZjl1QL9J74HED1B1emWvxOAQvMuSfnBkR8G70E
+D9qd1YnrEmM84FRrYgGtC2POJGnE25Fpvb/DZOuZXpFFTvQ5yuTJqcWLEgPZu45P
+2Wigpf1j523dkA15kwhY8+r58HTCULAsqfHedrFz1YXF8BXzecH7SzpXH2hlA36m
+oEGjFXrqAQe9YfLGLRnUrNgC12DWX2UzTqMuM5Q8Byj8SIE2oBkKXb5aW1zXkkJX
+U2pzzIglljQB8kjpkw4zTzZpEeoJwAMAQ4K73TkkV9YQOEdVJvqWYz5gWQI17qbm
+2gwrkYtA50+vhuO0wrIi9cJMZBOm46owBVDcMdDePgC5SURvnNjH+j1sx23IINXV
+ipViuv9t+YLNqO+8cPaAz225Yg7snCBnOO3RGwIDAQABoyYwJDAOBgNVHQ8BAf8E
+BAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBATANBgkqhkiG9w0BAQ0FAAOCAgEALWmm
+s3Z8cqtzpDJFZAsceNfnhgcYl1xkWbisoMe4K7hXTcp7EKlH2gsVl3YgATR5wWBw
+YlMc0rOqwIVdz5a5bY0QYrioxe1KyXZyhp4R/NvDMKQZ/p/wREI4smiAnEDwIN2R
+MS42SuKl2nIytJ4mIEAcNipGpk5sHQZqhQyipZ2hN3bEdZAGLH2/PpdaihHc0Jfj
+lBRpL1ewwORVbx9Jy6IvZoFfuzj5egalAp+VZlrXU3pBv0a+Zovo/7Q+M5tjBuIg
+MLr0R7n0J3FKIHxCwt1CHWTQ8R/QsLzhJDa1kf+SLTztHrUXqGJ/YAfpWDJh9pb2
+boGf7RBT0lFJhFOBpv2cEqTYP+1jWtlwGmUnfHI9bMCwO6B29bk4Xdlh57yGV6RF
+3VZ8dlN6ZBUc45vMYcWr1tLTRUzgArztMlEbloRb7n4x/UJpPV8zjracc8PyB/tl
+tlI2DZP/f+Gf0/Vv0M+tMu6DHjz1lSR+VNRadZ5yDRNPBh24qpPNSJ15HD26IwX+
+UQ44zVBtDxL0Y6ZMjhdSznz67eoymxYdlNHTYvw/zrg/+txje4M08i5PFFsSYN/m
+cEV5nSgJl14AEaXe+pS0hZgvDoLXMrqgruvCp06tO3LwNkDH3oGJOGP19jNCWGyd
+z7eQbiXNsCJGoeLKhxLj9IsVWyrLCCNZpojJdj0=
+-----END CERTIFICATE-----
+
+-----BEGIN CERTIFICATE-----
+MIIEyzCCArOgAwIBAgIBATANBgkqhkiG9w0BAQ0FADAVMRMwEQYDVQQLEwpSb290
+IFRFIENBMB4XDTE1MDcwMTE1NTAwOFoXDTM1MDcwODE1NTAwOFowFTETMBEGA1UE
+CxMKUm9vdCBURSBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIim
+2EeomY2b5zVgomN5EheGud1NfPbaH5h5MOrsu8c0JyaUIn3gBtJazuD4x2EJNObA
+NMigdJebc+yKP3fL8Z0fcj2JOwlrNS8ZcGWRucytYHr0ZEC1ZrkE2AysoXX8inw5
+ABnWzdXAW0WBfa5r1UQvZtU3oldk0UutvJ2Gc4mKhQRVsSf1QxDyZMkso/9DWJG/
+0aDLx7dAdosP7FNICpvJZp7mUoWgNvEBMXlirM0VOmoSaGmy7C75g+GhybpmBT9d
+UtDceWzBqH5nfR3vIIthbjdzX8szCtb307RN273zYE1n6RTPNdM54LGO4L6E6R2N
+3FMJS8H8zn5HnwjgDlKGG8OzFsmK3o+HvpEDc4p++bgm3Gc9gxjb971qOjlPQieD
+3jpmpSMPwg8qMuge16vbSwOOEru8vfi8c1Y9VJEZnD7rRxyDffyd9AZPnB+8sDND
+ZZv0Z4vsocSLsJjyqjRhDijbHQx6d5W6y/9ATyIz+sgg7r9B3d4IduxPRCNm7+T7
+9dg9NokwUJwfJrKTXDC/OofBzsGYo9TTmIdjbe01ZD9va1U2VVm87N4+J+xDdsod
+0eyp9CJ4z3ivm7NSplt56jYtkZ4J+kFzAIjU13zKxLVGqb0GTjISi1gwa5v5JGRX
+RTz7zEv4FDJj5A9XuxDkAVNxeEn5cBqS2xDZQTpDAgMBAAGjJjAkMA4GA1UdDwEB
+/wQEAwIBhjASBgNVHRMBAf8ECDAGAQH/AgECMA0GCSqGSIb3DQEBDQUAA4ICAQB/
+S9WHn3nBNl/PkRObDWIYutOI89IQQf9A7CRU2ndZH60Xy+eM59/CXbjU4vG2e9e6
+JcgrtSr6W+v+GLHCoVxOTI7IxM1+gjjLoHFfHNg97bXWRuHPLMSthTmSmiGC2q1r
+fJ/cTfs2/+cJ8gzm2CZ0hKs3GrSxQezKZ+ZJBSC1wff8VT+8giALd76I7kvywC+u
+4TnsoOzUCAC3mCR+laoIs8kmW+TBnZfgrskr0TjPdu5zCfZmK/SJSa8hOewYvrSc
+mUmTQeAhR4NroT9fLrKlsQglIgckhp1KgUedcJp8HmWQcaRSWsAvy9WeQaftv9TQ
+lWjEEjgdDwZ21qfl+o3wPAavC3il8pW8r8QWS5iFdzCpljYL3yfB5qbdhHfsEWD+
+oNWE4LCu+tq1PqgTNeSi1ff5RJCk3+sRJXDDK2Z6pCLhzUlmLSWlA1PmL3qLb3EM
+dXdPmpsuevs3MFIxfUOiZ65BeKLCKjY87fr/Z4a3cwu9AZebv9K4/Nt07EOhbTCv
+uAH7JcHDmRENPxUxrHIb/WIDhnPYUES+Vxr2oGVwSeNej9+22AGYxTgr7jY9A5Z4
+O+Sqfjbz818LTwYM+BTLGmHzRmgr85ygWpBwj9I2U+uEWKge2OksbCPQD9O3WJ+1
+DX9Bnr69S8ddGJVseNNtYsIvkE80HlyO+BqzASvuXQ==
+-----END CERTIFICATE-----
+
+
diff --git a/crypto/test/data/cert_chain_nl.data b/crypto/test/data/cert_chain_nl.data
new file mode 100644
index 000000000..feebf75af
--- /dev/null
+++ b/crypto/test/data/cert_chain_nl.data
@@ -0,0 +1,59 @@
+-----BEGIN CERTIFICATE-----
+MIIE+TCCAuGgAwIBAgIVAIb1Te5/365tZJu71WN94Kh2FpSoMA0GCSqGSIb3DQEB
+DQUAMBUxEzARBgNVBAsTClJvb3QgVEUgQ0EwHhcNMTUwNzAyMTU1MDA4WhcNMzUw
+NzA3MTU1MDA4WjAvMRQwEgYDVQQDEwsxMC4yMTEuNTUuMzEXMBUGA1UECxMOVEUg
+Uk1JIEhvc3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCU85zq
+Kwn80yW/QZjafyTnDiaPOr8X5u8OwTe+dbQPK2xSdT7d6FqEM8rmY9njGhue5XLH
+xKcUweVMt6E9h581qMrf39sldWMyoHxZiquPfs0t3zfMa3hYF5AONH5I3zdTZQj4
++5SD0mJugeM7YQ6eRs8qBdKLN/FwRWRAWQwDe3gF1gW5mgXfuo4Z3ufVscbJziJr
+L9gnYaqCfmI8MaDWeDNkB9biTYPXGh0oacUSpWUHyyrTlzodaKhd+m5FAgDUFlV4
+I9iv7YO4DT9sJmxmNFMrTN+c5HZjl1QL9J74HED1B1emWvxOAQvMuSfnBkR8G70E
+D9qd1YnrEmM84FRrYgGtC2POJGnE25Fpvb/DZOuZXpFFTvQ5yuTJqcWLEgPZu45P
+2Wigpf1j523dkA15kwhY8+r58HTCULAsqfHedrFz1YXF8BXzecH7SzpXH2hlA36m
+oEGjFXrqAQe9YfLGLRnUrNgC12DWX2UzTqMuM5Q8Byj8SIE2oBkKXb5aW1zXkkJX
+U2pzzIglljQB8kjpkw4zTzZpEeoJwAMAQ4K73TkkV9YQOEdVJvqWYz5gWQI17qbm
+2gwrkYtA50+vhuO0wrIi9cJMZBOm46owBVDcMdDePgC5SURvnNjH+j1sx23IINXV
+ipViuv9t+YLNqO+8cPaAz225Yg7snCBnOO3RGwIDAQABoyYwJDAOBgNVHQ8BAf8E
+BAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBATANBgkqhkiG9w0BAQ0FAAOCAgEALWmm
+s3Z8cqtzpDJFZAsceNfnhgcYl1xkWbisoMe4K7hXTcp7EKlH2gsVl3YgATR5wWBw
+YlMc0rOqwIVdz5a5bY0QYrioxe1KyXZyhp4R/NvDMKQZ/p/wREI4smiAnEDwIN2R
+MS42SuKl2nIytJ4mIEAcNipGpk5sHQZqhQyipZ2hN3bEdZAGLH2/PpdaihHc0Jfj
+lBRpL1ewwORVbx9Jy6IvZoFfuzj5egalAp+VZlrXU3pBv0a+Zovo/7Q+M5tjBuIg
+MLr0R7n0J3FKIHxCwt1CHWTQ8R/QsLzhJDa1kf+SLTztHrUXqGJ/YAfpWDJh9pb2
+boGf7RBT0lFJhFOBpv2cEqTYP+1jWtlwGmUnfHI9bMCwO6B29bk4Xdlh57yGV6RF
+3VZ8dlN6ZBUc45vMYcWr1tLTRUzgArztMlEbloRb7n4x/UJpPV8zjracc8PyB/tl
+tlI2DZP/f+Gf0/Vv0M+tMu6DHjz1lSR+VNRadZ5yDRNPBh24qpPNSJ15HD26IwX+
+UQ44zVBtDxL0Y6ZMjhdSznz67eoymxYdlNHTYvw/zrg/+txje4M08i5PFFsSYN/m
+cEV5nSgJl14AEaXe+pS0hZgvDoLXMrqgruvCp06tO3LwNkDH3oGJOGP19jNCWGyd
+z7eQbiXNsCJGoeLKhxLj9IsVWyrLCCNZpojJdj0=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIEyzCCArOgAwIBAgIBATANBgkqhkiG9w0BAQ0FADAVMRMwEQYDVQQLEwpSb290
+IFRFIENBMB4XDTE1MDcwMTE1NTAwOFoXDTM1MDcwODE1NTAwOFowFTETMBEGA1UE
+CxMKUm9vdCBURSBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIim
+2EeomY2b5zVgomN5EheGud1NfPbaH5h5MOrsu8c0JyaUIn3gBtJazuD4x2EJNObA
+NMigdJebc+yKP3fL8Z0fcj2JOwlrNS8ZcGWRucytYHr0ZEC1ZrkE2AysoXX8inw5
+ABnWzdXAW0WBfa5r1UQvZtU3oldk0UutvJ2Gc4mKhQRVsSf1QxDyZMkso/9DWJG/
+0aDLx7dAdosP7FNICpvJZp7mUoWgNvEBMXlirM0VOmoSaGmy7C75g+GhybpmBT9d
+UtDceWzBqH5nfR3vIIthbjdzX8szCtb307RN273zYE1n6RTPNdM54LGO4L6E6R2N
+3FMJS8H8zn5HnwjgDlKGG8OzFsmK3o+HvpEDc4p++bgm3Gc9gxjb971qOjlPQieD
+3jpmpSMPwg8qMuge16vbSwOOEru8vfi8c1Y9VJEZnD7rRxyDffyd9AZPnB+8sDND
+ZZv0Z4vsocSLsJjyqjRhDijbHQx6d5W6y/9ATyIz+sgg7r9B3d4IduxPRCNm7+T7
+9dg9NokwUJwfJrKTXDC/OofBzsGYo9TTmIdjbe01ZD9va1U2VVm87N4+J+xDdsod
+0eyp9CJ4z3ivm7NSplt56jYtkZ4J+kFzAIjU13zKxLVGqb0GTjISi1gwa5v5JGRX
+RTz7zEv4FDJj5A9XuxDkAVNxeEn5cBqS2xDZQTpDAgMBAAGjJjAkMA4GA1UdDwEB
+/wQEAwIBhjASBgNVHRMBAf8ECDAGAQH/AgECMA0GCSqGSIb3DQEBDQUAA4ICAQB/
+S9WHn3nBNl/PkRObDWIYutOI89IQQf9A7CRU2ndZH60Xy+eM59/CXbjU4vG2e9e6
+JcgrtSr6W+v+GLHCoVxOTI7IxM1+gjjLoHFfHNg97bXWRuHPLMSthTmSmiGC2q1r
+fJ/cTfs2/+cJ8gzm2CZ0hKs3GrSxQezKZ+ZJBSC1wff8VT+8giALd76I7kvywC+u
+4TnsoOzUCAC3mCR+laoIs8kmW+TBnZfgrskr0TjPdu5zCfZmK/SJSa8hOewYvrSc
+mUmTQeAhR4NroT9fLrKlsQglIgckhp1KgUedcJp8HmWQcaRSWsAvy9WeQaftv9TQ
+lWjEEjgdDwZ21qfl+o3wPAavC3il8pW8r8QWS5iFdzCpljYL3yfB5qbdhHfsEWD+
+oNWE4LCu+tq1PqgTNeSi1ff5RJCk3+sRJXDDK2Z6pCLhzUlmLSWlA1PmL3qLb3EM
+dXdPmpsuevs3MFIxfUOiZ65BeKLCKjY87fr/Z4a3cwu9AZebv9K4/Nt07EOhbTCv
+uAH7JcHDmRENPxUxrHIb/WIDhnPYUES+Vxr2oGVwSeNej9+22AGYxTgr7jY9A5Z4
+O+Sqfjbz818LTwYM+BTLGmHzRmgr85ygWpBwj9I2U+uEWKge2OksbCPQD9O3WJ+1
+DX9Bnr69S8ddGJVseNNtYsIvkE80HlyO+BqzASvuXQ==
+-----END CERTIFICATE-----
+
+
diff --git a/crypto/test/data/cms/sigs/SignedMSPkcs7.sig b/crypto/test/data/cms/sigs/SignedMSPkcs7.sig
new file mode 100644
index 000000000..df9a09b0d
--- /dev/null
+++ b/crypto/test/data/cms/sigs/SignedMSPkcs7.sig
Binary files differdiff --git a/crypto/test/data/cms/sigs/rawsha256nonull.p7m b/crypto/test/data/cms/sigs/rawsha256nonull.p7m
new file mode 100644
index 000000000..5d29760cb
--- /dev/null
+++ b/crypto/test/data/cms/sigs/rawsha256nonull.p7m
Binary files differdiff --git a/crypto/test/data/qvRooCa3.crt b/crypto/test/data/qvRooCa3.crt
new file mode 100644
index 000000000..969322b95
--- /dev/null
+++ b/crypto/test/data/qvRooCa3.crt
@@ -0,0 +1,38 @@
+-----BEGIN CERTIFICATE-----
+MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x
+GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv
+b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV
+BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W
+YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM
+V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB
+4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr
+H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd
+8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv
+vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT
+mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe
+btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc
+T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt
+WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ
+c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A
+4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD
+VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG
+CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0
+aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0
+aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu
+dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw
+czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G
+A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC
+TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg
+Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0
+7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem
+d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd
++LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B
+4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN
+t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x
+DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57
+k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s
+zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j
+Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT
+mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK
+4SVhM7JZG+Ju1zdXtg2pEto=
+-----END CERTIFICATE-----
diff --git a/crypto/test/data/suvaEE.crt b/crypto/test/data/suvaEE.crt
new file mode 100644
index 000000000..cc8e8ac8a
--- /dev/null
+++ b/crypto/test/data/suvaEE.crt
@@ -0,0 +1,32 @@
+-----BEGIN CERTIFICATE-----
+MIIFfjCCA2agAwIBAgIIBHTrx4eZAPkwDQYJKoZIhvcNAQEFBQAwcDELMAkGA1UE
+BhMCQ0gxDzANBgNVBAgTBkx1emVybjEPMA0GA1UEBxMGTHV6ZXJuMQ0wCwYDVQQK
+EwRTdXZhMQswCQYDVQQLEwJJRjEjMCEGA1UEAxMaU3V2YSBTZWN1cmUgTWFpbCBJ
+Q0EgMSAoMSkwHhcNMTQwODA0MTE0OTIxWhcNMTYwODAzMTI0OTIxWjCBhTELMAkG
+A1UEBhMCQ0gxDzANBgNVBAgMBkx1emVybjEPMA0GA1UEBwwGTHV6ZXJuMQ0wCwYD
+VQQKDARTdXZhMQswCQYDVQQLDAJJRjEUMBIGA1UEAwwLTmljbyBNYXJpdHoxIjAg
+BgkqhkiG9w0BCQEWE25pY28ubWFyaXR6QHN1dmEuY2gwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQCweUvvHneU32sriCJJBl18xKqUE9DrGUFDhNCpgKLd
+OhLKZJRgG/rpD1qn9gMI7KnnubbWpW3HCW+6nXT8wPpqMBNpjVgDwL/gb0eKMRvk
+QcOs9kvaIt142MGCMZIlLBL/7/JTJhRi9tysJq8wacymqTDIh4MsejatsmXzRCx4
+tUIuNgFfObDGz0viSUplDz2xlVElRYQ5GRVVRvZF2lAlA0ymhbJwPvKRuf9ou7dh
+wlG7nDgUMQnt4a+88sFTIogN11u7H5TiHgDArI8ovJjHFT7SZw/XgMsSM5NVcv1J
+cSoGP4xQ1VdScr80HaVK+GIaJIiG9VcGMw4t/vwBSrBZAgMBAAGjggEEMIIBADAT
+BgNVHSUEDDAKBggrBgEFBQcDBDALBgNVHQ8EBAMCBPAwHQYDVR0OBBYEFMuyfXI4
+PH87MolGzEoxWg4YMwKmMB8GA1UdIwQYMBaAFHrwc1/OwXgGLLVN2K5T/IQtgWYo
+MCEGCWCGSAGG+EIBDQQUExJTdXZhIFNlY3VyZSBFLU1haWwwHgYDVR0RBBcwFYET
+bmljby5tYXJpdHpAc3V2YS5jaDAMBgNVHRMBAf8EAjAAMBEGCWCGSAGG+EIBAQQE
+AwIFIDA4BgNVHR8EMTAvMC2gK6AphidodHRwOi8vcGtpLnN1dmEuY2gvY3JsL3N1
+dmFtaWNhMSgxKS5jcmwwDQYJKoZIhvcNAQEFBQADggIBADCszfdfxrt+LTgh3MMp
+R+7Yt8GZT5svQDLmpmUqkDcY5dHIvfSu/YBF/wVDKz+wbegTjonwr1do9Msc8lRl
+BAHfFk23os6MZJr4efpuBaJXFKJN23T6U9nZgphDAroA5MreF0MVkTnQQMvLL+tu
+rXAPFQb0XKl5K4xWDcn5wKdcA7UZsLW2guZm7LiWuPYiNVk5QXg3Z9awZfquFGXw
+1uOCfhIv5IlfVwXf94kok6sy3tnk3IDuYLBfaAVHpAMgyocgn1XU/aAy7y+bUUHe
+AosKkV6AZ/5pirZv8yDuB37sIEAiOfMc3cCYk/ACbw+C18XcGXUKxWNBG+LUiJ/n
+lvxnqCWOAS4/U52I0bmbXYMZ9Iz8dYoMe19iG2sQHMhw4S25O/oKhllzmren1BNd
+EA/EZdbmqjmGDfvY6ELQpyeTUz6u/4Hfcdd/8IavcYXfBo0kpPJFm6epjMBSw2Bi
+D1r1U+8oGNwoTce++Ch30eEjuxyMFTDOXzJObJHsZmcPP1fxKch5yGX+cF2oDWju
+GOvviu9YxVTC4m+vwAwmmKSl7XylrVcJmXCh7u92wvgw8kXqA0R/P/gn8QQtQ5Ge
+/a6vJRyhDVEP8wWmyebLZYlHZDrosD191d92SKaMRg7HDAH0nZ6wtlgxD20JyDO0
+FIIJq/d36mNrHPbd7Y4SxiAX
+-----END CERTIFICATE-----
diff --git a/crypto/test/data/suvaEmail1.crt b/crypto/test/data/suvaEmail1.crt
new file mode 100644
index 000000000..a7bcfdd6c
--- /dev/null
+++ b/crypto/test/data/suvaEmail1.crt
@@ -0,0 +1,39 @@
+-----BEGIN CERTIFICATE-----
+MIIG5DCCBMygAwIBAgIKF/12kwABAAACGDANBgkqhkiG9w0BAQUFADBGMQswCQYD
+VQQGEwJDSDEPMA0GA1UECBMGTHV6ZXJuMQ0wCwYDVQQKEwRTdXZhMRcwFQYDVQQD
+Ew5TdXZhIFJvb3QgQ0EgMTAeFw0xNDA1MTcwODAwNDJaFw0yNDA1MDcxMzEyMDNa
+MHAxCzAJBgNVBAYTAkNIMQ8wDQYDVQQIEwZMdXplcm4xDzANBgNVBAcTBkx1emVy
+bjENMAsGA1UEChMEU3V2YTELMAkGA1UECxMCSUYxIzAhBgNVBAMTGlN1dmEgU2Vj
+dXJlIE1haWwgSUNBIDEgKDEpMIICIDANBgkqhkiG9w0BAQEFAAOCAg0AMIICCAKC
+AgEAueI8pNseKiE5+3adL3ZBQQ5g6ajOAY0KI3TCV5YKt8OjFbNviV+ja9mwrhMP
+hx+QaTQruyCbi6FcNQlLxhilrjKX30//J3GvPc65t8Vcs2XsyC8u6KJaaQG8kl89
+j1/F76Ary/MiFU5ZaZuyj9vwDuHjRK2Vq8PxlHNRwGQFXI5y1LJPd/DUM6hY/sub
+x//rknAJYPELKj5skFGz+prQR4ZgXegjN/9F1mmGFUEdCjoROV5m91asp3KFcK3L
+DyQ5WC3JVm1zSvUTpGHKVqKXX+6WvG8wbv2AIvf8XLVI92bNB6xXpV2Tq05mLx48
+txfPVez4gfGkjhAK8StFKPEJs8CIvGV1XGUGM79VSw86rN6qT/A6kpGU1FsNwHv8
+HP3BArQLR3L+mQEnlulXhKE4K6hbx9seOhufhTORoW3F2QDW71SFWag5KV+r64zC
+uE9aHy20seLs6rK4+lgV1SLMsew5Ot3AKfXbCVl2SG6gwE1M6V0DYRM787tdEVo/
+CMzP1FrWj96DX2aAU6BiRC36Jjd1HrJuIVmuXvVsE6YmfRIzSYKZBT/ZR/7knl13
+fTuR6K1kiWZs4Alq6mrVXxqcXOXR8k8NzNK9RI+XiYOuSAGHu2uX4pDXiEro7AFd
+o/jqIZozuLZ2C7B7Yigf39I2WEEM4zILqSbIthLGcOJn0/0CAQOjggGqMIIBpjAS
+BgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUevBz
+X87BeAYstU3YrlP8hC2BZigwHwYDVR0jBBgwFoAUPFQUaTyz0/rgxsL2+kdFRxXK
+KmowQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL3BraS5zdXZhLmNoL2NybC9TdXZh
+JTIwUm9vdCUyMENBJTIwMSgxKS5jcmwwcwYIKwYBBQUHAQEEZzBlMCMGCCsGAQUF
+BzABhhdodHRwOi8vcGtpLnN1dmEuY2gvb2NzcDA+BggrBgEFBQcwAoYyaHR0cDov
+L3BraS5zdXZhLmNoL2NydC9TdXZhJTIwUm9vdCUyMENBJTIwMSgxKS5jcnQwPAYJ
+KwYBBAGCNxUHBC8wLQYlKwYBBAGCNxUIxZdWhpShU4LRlzCD+65khNfBO0aHve1v
+hcKqLQIBZAIBBzAeBgNVHSUEFzAVBggrBgEFBQcDBAYJKwYBBAGCNxUFMCgGCSsG
+AQQBgjcVCgQbMBkwCgYIKwYBBQUHAwQwCwYJKwYBBAGCNxUFMA0GCSqGSIb3DQEB
+BQUAA4ICAQDeAhIR0DCUS4tHJCJAPgHH/uMQcgV3qKNkZznmaKQ0kRl2JISbojrv
+6WnIr+gcyoBPbI01QNbe7Dh73mMK/ezUZ04B9z9UBUvV5l7rCOL28Hnz/zmZZX+T
+q3jxtQJPV4w2b9tuo8/vEUirEySmkmN6IGbu1epAhp9mCKUNjC6Oe3JwsMX/ouZN
+Op2PPQ82fjVk8zlUpVX9qfRc9XmW992JrUe/npWqdJYYSJY1vFB9b6gMGiwOms1H
+oXuDz0BQXp0m0D+7VjY8qi8vN7N8/Zy6EC/453ogal20nhMEiihGkvD68RyBjQO6
+kEWcjUizcC0vjcH6W+EyQeJ5VDTxv/GlSA2SHZWFJ7/T1dY+bHBjHr7aqptQzZeU
+cWv0BfFdlEMkzZgOLRrmHKdTCGa/11vi3T12SzISwyGakPKrA8IaJCzNQO3/6dc8
+DBX8p9RO54VrSDsDSfTueofMnBpUJABMe1Eohqsj0sZv0n8cK85A6utQPuSxmgV2
+IAXdJMJcGAZ6PDKKCJYVVdHOeFEdUMh/fh6QGd1Iz0QMfMeiZODTo92loHnW0HPL
+aVTdoQmn3K1yVFUrdYp/OJz4UDWFb2k4Du6GeQl1jqc2VREPohvvbDSJ9pgE3Oh2
+DEN7RZ7zK/FwLZeo8Qgo4yguznSzp3zLrUwLTewRNU1QbEiy9tIclQ==
+-----END CERTIFICATE-----
diff --git a/crypto/test/data/suvaRoot1.crt b/crypto/test/data/suvaRoot1.crt
new file mode 100644
index 000000000..83cfe6686
--- /dev/null
+++ b/crypto/test/data/suvaRoot1.crt
@@ -0,0 +1,46 @@
+-----BEGIN CERTIFICATE-----
+MIIH4jCCBcqgAwIBAgIUZ6RtH7xmDM0r66IKSlpCZNrlRfYwDQYJKoZIhvcNAQEF
+BQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZ
+BgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0xNDA1MDcxMzEyMDNaFw0yNDA1
+MDcxMzEyMDNaMEYxCzAJBgNVBAYTAkNIMQ8wDQYDVQQIEwZMdXplcm4xDTALBgNV
+BAoTBFN1dmExFzAVBgNVBAMTDlN1dmEgUm9vdCBDQSAxMIICIjANBgkqhkiG9w0B
+AQEFAAOCAg8AMIICCgKCAgEA9KfSFwpwbRnrfnMk1DkKQguwEKg6crSLKS31CU9E
+ShdmIzMQyo9k4doec6c0cpubk17VlEEE8SmFSqwmLBRo+65kR5c3X4MeI0Fv1ZXH
+WV+ZiaK+CVPf4OFNNCNuEFc1qnNxyWGvGVI+KMk1Lmrpda6h5GkMpFdxBRGq4RkU
+aw41ljJgY9+UapZTl0b39XEeEgQshY/hKEKPeRZNeTHBFWFTsAZxZBSH0bz35zfh
+X1oQLad3b5Q2Nw1utEcai4I9DnTyAQ7wRtius217twXERdpeLdTurKe7TVqHcyBS
+ziTpsCewINJ1S69a1E7Z59SNorOEgGIS2Z89fIlwYVQkcW5pLZL+Q5UC1rcD/FWq
+m4rIOrjM0AYcLEiScmNYYgLEPrXvh1BVMkc+SIqiQ7JhlzXSDZmMBcqrlVilp2oz
+lyuCRlMpGdlUqe0BD3JY/vfOZRm+NHfys4mmLIQhLJgX2vH5UOeAzdQ2pkpFdHNq
+1tMLITr108NcZ62updidyVFy+8kbr7NKawmp03MtYjdYqEi2lDNgJcwk17uoxhbv
+LEYvSNM+wMc73duO97pOrgbTrIIHeBdgjP/ZqHkW/4ZtxUpxFSxqoBgUVw6IHTn9
+2cYBmouDdhEYhnFhcEVqYP5N0JjT9nFzWL/EU+Lgk8y3x59luxaGJV9tEU9P0MIy
+cBUCAwEAAaOCAscwggLDMBIGA1UdEwEB/wQIMAYBAf8CAQEwcwYIKwYBBQUHAQEE
+ZzBlMCsGCCsGAQUFBzABhh9odHRwOi8vb2NzcC5xdW92YWRpc2dsb2JhbC5jb20v
+MDYGCCsGAQUFBzAChipodHRwOi8vdHJ1c3QucXVvdmFkaXNnbG9iYWwuY29tL3F2
+cmNhMy5jcnQwgdAGA1UdIASByDCBxTCBwgYMKwYBBAG+WAADhFgAMIGxMIGDBggr
+BgEFBQcCAjB3GnVBbnkgdXNlIG9mIHRoaXMgQ2VydGlmaWNhdGUgY29uc3RpdHV0
+ZXMgYWNjZXB0YW5jZSBvZiB0aGUgU3V2YSBDZXJ0aWZpY2F0ZSBQb2xpY3kgLyBD
+ZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wKQYIKwYBBQUHAgEWHWh0
+dHA6Ly9wa2kuc3V2YS5jaC9yZXBvc2l0b3J5MGQGA1UdHgRdMFugWTAKgQhAc3V2
+YS5jaDANgQtAc3V2YW5ldC5jaDAPgQ1Ac3V2YW5ldDYyLmNoMA+BDUBzdXZhbmV0
+NzcuY2gwDIEKQHN1dmE2Mi5jaDAMgQpAc3V2YTc3LmNoMA4GA1UdDwEB/wQEAwIB
+BjB0BgNVHSUEbTBrBggrBgEFBQcDBAYIKwYBBQUHAwIGCCsGAQUFBwMJBgorBgEE
+AYI3CgMEBgorBgEEAYI3FAICBgorBgEEAYI3FAIBBgcrBgEFAgMFBggrBgEFBQgC
+AgYJKwYBBAGCNxUFBgkrBgEEAYI3FQYwHwYDVR0jBBgwFoAU8sAT4IJDPvvuL2cy
+ljVc27jLAtAwOQYDVR0fBDIwMDAuoCygKoYoaHR0cDovL2NybC5xdW92YWRpc2ds
+b2JhbC5jb20vcXZyY2EzLmNybDAdBgNVHQ4EFgQUPFQUaTyz0/rgxsL2+kdFRxXK
+KmowDQYJKoZIhvcNAQEFBQADggIBADsk54ImQSM2LcLtwpH5s3NPn/qpua22SUyH
+sujqy8vHEAOS0KPbN+Jnq4KpexylTVHQ3ybgHSQt6SZ+/NSBHO8eAAyqZyWjenyk
+UCcL7TNO82tD7lkuq+eo+BIsq9AJTI0gGRqG/wFyvNpVssZ0bFdqGNq0aM74NHWD
+7LRa6toC1I+YNpvelSlZvGfEpm0G7e04AE3kzFnaemG3RwRY2mUtT5Aby5vpfouh
+IbdF4t1NEyC9ExFOkEjZ3P1AAoJgxQC3T7B1Mo6r03pcBdd9LrjjVJidUyj+j/ha
+faZo4e1wJeU09UtzVSzGb1GA8QHOJMY7VeA0qLg4qfZdeoDxrCZJKn/pZP2D6dQs
+0Za1args4EUJmdVFsuFNc1DsM1EXTD5o9dHkX/cKPv6eMRehP7emNjJgmcIv1rX3
+sotSJA06D+5LW6ZkuWdS2uArCta8YgrVtefRMNj2nhVGafLt7tE819E0fqnaknGR
+RgfNRFEMeTIU29RtgvzbpYtCK+O1v7a3x55mt/RbMhtruns3OOVAY+l7nW1y51Xb
+A8bPOZc7fREndSacNCpK37Or3AhE4Uneylz+rN25H2hL8OT/xAXxj6IcPRuD2SDH
+nvXiM0xeqCQpfDNv/35uNSMdpsA75GZwRpvt0fMc5r0AwtwBFZX7X4KtULoNxLNb
+JZxATf23
+-----END CERTIFICATE-----
+
diff --git a/crypto/test/src/asn1/test/SignerLocationUnitTest.cs b/crypto/test/src/asn1/test/SignerLocationUnitTest.cs
index a0104dc81..e4666740f 100644
--- a/crypto/test/src/asn1/test/SignerLocationUnitTest.cs
+++ b/crypto/test/src/asn1/test/SignerLocationUnitTest.cs
@@ -2,8 +2,8 @@ using System;
using NUnit.Framework;
-using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Esf;
+using Org.BouncyCastle.Asn1.X500;
using Org.BouncyCastle.Utilities.Test;
namespace Org.BouncyCastle.Asn1.Tests
@@ -23,17 +23,17 @@ namespace Org.BouncyCastle.Asn1.Tests
SignerLocation sl = new SignerLocation(countryName, null, null);
- CheckConstruction(sl, countryName, null, null);
+ CheckConstruction(sl, DirectoryString.GetInstance(countryName), null, null);
DerUtf8String localityName = new DerUtf8String("Melbourne");
sl = new SignerLocation(null, localityName, null);
- CheckConstruction(sl, null, localityName, null);
+ CheckConstruction(sl, null, DirectoryString.GetInstance(localityName), null);
sl = new SignerLocation(countryName, localityName, null);
- CheckConstruction(sl, countryName, localityName, null);
+ CheckConstruction(sl, DirectoryString.GetInstance(countryName), DirectoryString.GetInstance(localityName), null);
Asn1Sequence postalAddress = new DerSequence(
new DerUtf8String("line 1"),
@@ -45,11 +45,11 @@ namespace Org.BouncyCastle.Asn1.Tests
sl = new SignerLocation(countryName, null, postalAddress);
- CheckConstruction(sl, countryName, null, postalAddress);
+ CheckConstruction(sl, DirectoryString.GetInstance(countryName), null, postalAddress);
sl = new SignerLocation(countryName, localityName, postalAddress);
- CheckConstruction(sl, countryName, localityName, postalAddress);
+ CheckConstruction(sl, DirectoryString.GetInstance(countryName), DirectoryString.GetInstance(localityName), postalAddress);
sl = SignerLocation.GetInstance(null);
@@ -117,9 +117,9 @@ namespace Org.BouncyCastle.Asn1.Tests
private void CheckConstruction(
SignerLocation sl,
- DerUtf8String countryName,
- DerUtf8String localityName,
- Asn1Sequence postalAddress)
+ DirectoryString countryName,
+ DirectoryString localityName,
+ Asn1Sequence postalAddress)
{
CheckValues(sl, countryName, localityName, postalAddress);
@@ -137,9 +137,9 @@ namespace Org.BouncyCastle.Asn1.Tests
private void CheckValues(
SignerLocation sl,
- DerUtf8String countryName,
- DerUtf8String localityName,
- Asn1Sequence postalAddress)
+ DirectoryString countryName,
+ DirectoryString localityName,
+ Asn1Sequence postalAddress)
{
if (countryName != null)
{
diff --git a/crypto/test/src/cms/test/SignedDataTest.cs b/crypto/test/src/cms/test/SignedDataTest.cs
index 89f7eea7d..29d0464c2 100644
--- a/crypto/test/src/cms/test/SignedDataTest.cs
+++ b/crypto/test/src/cms/test/SignedDataTest.cs
@@ -672,6 +672,24 @@ namespace Org.BouncyCastle.Cms.Tests
VerifySignatures(s, hash);
}
+ [Test]
+ public void TestRawSha256MissingNull()
+ {
+ byte[] document = GetInput("rawsha256nonull.p7m");
+
+ CmsSignedData s = new CmsSignedData(document);
+
+ IX509Store certStore = s.GetCertificates("Collection");
+ foreach (SignerInformation signerInformation in s.GetSignerInfos().GetSigners())
+ {
+ ICollection certCollection = certStore.GetMatches(signerInformation.SignerID);
+ foreach (X509Certificate cert in certCollection)
+ {
+ Assert.IsTrue(signerInformation.Verify(cert), "raw sig failed");
+ }
+ }
+ }
+
[Test]
public void TestSha1WithRsaEncapsulated()
{
diff --git a/crypto/test/src/crypto/test/DSTU7564Test.cs b/crypto/test/src/crypto/test/DSTU7564Test.cs
index 21a3a91da..c89962653 100644
--- a/crypto/test/src/crypto/test/DSTU7564Test.cs
+++ b/crypto/test/src/crypto/test/DSTU7564Test.cs
@@ -46,16 +46,16 @@ namespace Org.BouncyCastle.Crypto.Tests
public override void PerformTest()
{
base.PerformTest();
-
- hash256Tests();
- hash384Tests();
- hash512Tests();
- macTests();
- overflowTest();
- }
- private void overflowTest()
- {
+ hash256Tests();
+ hash384Tests();
+ hash512Tests();
+ macTests();
+ overflowTest();
+ }
+
+ private void overflowTest()
+ {
int macBitSize = 256;
byte[] input = new byte[1024];
for (int i = 0; i != input.Length; i++)
@@ -300,29 +300,28 @@ namespace Org.BouncyCastle.Crypto.Tests
}
}
- private void macTests()
- {
-
- //test1
- int macBitSize = 256;
- byte[] input = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E");
- byte[] key = Hex.Decode("1F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100");
+ private void macTests()
+ {
+ //test1
+ int macBitSize = 256;
+ byte[] input = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E");
+ byte[] key = Hex.Decode("1F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100");
- byte[] expectedMac = Hex.Decode("B60594D56FA79BA210314C72C2495087CCD0A99FC04ACFE2A39EF669925D98EE");
- byte[] mac = new byte[macBitSize / 8];
+ byte[] expectedMac = Hex.Decode("B60594D56FA79BA210314C72C2495087CCD0A99FC04ACFE2A39EF669925D98EE");
+ byte[] mac = new byte[macBitSize / 8];
- Dstu7564Mac dstu7564mac = new Dstu7564Mac(macBitSize);
+ Dstu7564Mac dstu7564mac = new Dstu7564Mac(macBitSize);
- dstu7564mac.Init(new KeyParameter(key));
- dstu7564mac.BlockUpdate(input, 0, input.Length);
- dstu7564mac.DoFinal(mac, 0);
+ dstu7564mac.Init(new KeyParameter(key));
+ dstu7564mac.BlockUpdate(input, 0, input.Length);
+ dstu7564mac.DoFinal(mac, 0);
- if (!Arrays.AreEqual(expectedMac, mac))
- {
- Fail("Failed mac test 1 - expected "
- + Hex.ToHexString(expectedMac)
- + " got " + Hex.ToHexString(mac));
- }
+ if (!Arrays.AreEqual(expectedMac, mac))
+ {
+ Fail("Failed mac test 1 - expected "
+ + Hex.ToHexString(expectedMac)
+ + " got " + Hex.ToHexString(mac));
+ }
//test1a
input = Hex.Decode("0001020304050607");
@@ -346,290 +345,276 @@ namespace Org.BouncyCastle.Crypto.Tests
//test 2
macBitSize = 384;
- input = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E");
- key = Hex.Decode("2F2E2D2C2B2A292827262524232221201F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100");
+ input = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E");
+ key = Hex.Decode("2F2E2D2C2B2A292827262524232221201F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100");
- expectedMac = Hex.Decode("BEBFD8D730336F043ABACB41829E79A4D320AEDDD8D14024D5B805DA70C396FA295C281A38B30AE728A304B3F5AE490E");
- mac = new byte[macBitSize / 8];
+ expectedMac = Hex.Decode("BEBFD8D730336F043ABACB41829E79A4D320AEDDD8D14024D5B805DA70C396FA295C281A38B30AE728A304B3F5AE490E");
+ mac = new byte[macBitSize / 8];
- dstu7564mac = new Dstu7564Mac(macBitSize);
+ dstu7564mac = new Dstu7564Mac(macBitSize);
- dstu7564mac.Init(new KeyParameter(key));
- dstu7564mac.BlockUpdate(input, 0, input.Length);
- dstu7564mac.DoFinal(mac, 0);
+ dstu7564mac.Init(new KeyParameter(key));
+ dstu7564mac.BlockUpdate(input, 0, input.Length);
+ dstu7564mac.DoFinal(mac, 0);
- if (!Arrays.AreEqual(expectedMac, mac))
- {
- Fail("Failed mac test 2 - expected "
- + Hex.ToHexString(expectedMac)
- + " got " + Hex.ToHexString(mac));
- }
+ if (!Arrays.AreEqual(expectedMac, mac))
+ {
+ Fail("Failed mac test 2 - expected "
+ + Hex.ToHexString(expectedMac)
+ + " got " + Hex.ToHexString(mac));
+ }
- //test 3
- macBitSize = 512;
- input = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E");
- key = Hex.Decode("3F3E3D3C3B3A393837363534333231302F2E2D2C2B2A292827262524232221201F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100");
+ //test 3
+ macBitSize = 512;
+ input = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E");
+ key = Hex.Decode("3F3E3D3C3B3A393837363534333231302F2E2D2C2B2A292827262524232221201F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100");
- expectedMac = Hex.Decode("F270043C06A5C37E65D9D791C5FBFB966E5EE709F8F54019C9A55B76CA40B70100579F269CEC24E347A9D864614CF3ABBF6610742E4DB3BD2ABC000387C49D24");
- mac = new byte[macBitSize / 8];
+ expectedMac = Hex.Decode("F270043C06A5C37E65D9D791C5FBFB966E5EE709F8F54019C9A55B76CA40B70100579F269CEC24E347A9D864614CF3ABBF6610742E4DB3BD2ABC000387C49D24");
+ mac = new byte[macBitSize / 8];
- dstu7564mac = new Dstu7564Mac(macBitSize);
+ dstu7564mac = new Dstu7564Mac(macBitSize);
- dstu7564mac.Init(new KeyParameter(key));
- dstu7564mac.BlockUpdate(input, 0, input.Length);
- dstu7564mac.DoFinal(mac, 0);
+ dstu7564mac.Init(new KeyParameter(key));
+ dstu7564mac.BlockUpdate(input, 0, input.Length);
+ dstu7564mac.DoFinal(mac, 0);
- if (!Arrays.AreEqual(expectedMac, mac))
- {
- Fail("Failed mac test 3 - expected "
- + Hex.ToHexString(expectedMac)
- + " got " + Hex.ToHexString(mac));
+ if (!Arrays.AreEqual(expectedMac, mac))
+ {
+ Fail("Failed mac test 3 - expected "
+ + Hex.ToHexString(expectedMac)
+ + " got " + Hex.ToHexString(mac));
+ }
}
- }
-
- private void hash512Tests()
- {
-
- int hashBitSize = 512;
-
- //test 1
- byte[] input = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F");
- byte[] expectedHash = Hex.Decode("3813E2109118CDFB5A6D5E72F7208DCCC80A2DFB3AFDFB02F46992B5EDBE536B3560DD1D7E29C6F53978AF58B444E37BA685C0DD910533BA5D78EFFFC13DE62A");
- byte[] hash = new byte[hashBitSize / 8];
-
-
- Dstu7564Digest dstu7564 = new Dstu7564Digest(hashBitSize);
- dstu7564.BlockUpdate(input, 0, input.Length);
- dstu7564.DoFinal(hash, 0);
- if (!Arrays.AreEqual(expectedHash, hash))
+ private void hash512Tests()
{
- Fail("Failed hash-512 test 1 - expected "
- + Hex.ToHexString(expectedHash)
- + " got " + Hex.ToHexString(hash));
- }
-
- //test 2
- input = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F");
- expectedHash = Hex.Decode("76ED1AC28B1D0143013FFA87213B4090B356441263C13E03FA060A8CADA32B979635657F256B15D5FCA4A174DE029F0B1B4387C878FCC1C00E8705D783FD7FFE");
- hash = new byte[hashBitSize / 8];
+ int hashBitSize = 512;
+ //test 1
+ byte[] input = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F");
+ byte[] expectedHash = Hex.Decode("3813E2109118CDFB5A6D5E72F7208DCCC80A2DFB3AFDFB02F46992B5EDBE536B3560DD1D7E29C6F53978AF58B444E37BA685C0DD910533BA5D78EFFFC13DE62A");
+ byte[] hash = new byte[hashBitSize / 8];
- dstu7564 = new Dstu7564Digest(hashBitSize);
- dstu7564.BlockUpdate(input, 0, input.Length);
- dstu7564.DoFinal(hash, 0);
-
- if (!Arrays.AreEqual(expectedHash, hash))
- {
- Fail("Failed hash-512 test 2 - expected "
- + Hex.ToHexString(expectedHash)
- + " got " + Hex.ToHexString(hash));
- }
-
- //test 3
- input = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF");
- expectedHash = Hex.Decode("0DD03D7350C409CB3C29C25893A0724F6B133FA8B9EB90A64D1A8FA93B56556611EB187D715A956B107E3BFC76482298133A9CE8CBC0BD5E1436A5B197284F7E");
- hash = new byte[hashBitSize / 8];
+ Dstu7564Digest dstu7564 = new Dstu7564Digest(hashBitSize);
+ dstu7564.BlockUpdate(input, 0, input.Length);
+ dstu7564.DoFinal(hash, 0);
+ if (!Arrays.AreEqual(expectedHash, hash))
+ {
+ Fail("Failed hash-512 test 1 - expected "
+ + Hex.ToHexString(expectedHash)
+ + " got " + Hex.ToHexString(hash));
+ }
- dstu7564 = new Dstu7564Digest(hashBitSize);
- dstu7564.BlockUpdate(input, 0, input.Length);
- dstu7564.DoFinal(hash, 0);
+ //test 2
+ input = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F");
+ expectedHash = Hex.Decode("76ED1AC28B1D0143013FFA87213B4090B356441263C13E03FA060A8CADA32B979635657F256B15D5FCA4A174DE029F0B1B4387C878FCC1C00E8705D783FD7FFE");
+ hash = new byte[hashBitSize / 8];
- if (!Arrays.AreEqual(expectedHash, hash))
- {
- Fail("Failed hash-512 test 3 - expected "
- + Hex.ToHexString(expectedHash)
- + " got " + Hex.ToHexString(hash));
- }
+ dstu7564 = new Dstu7564Digest(hashBitSize);
+ dstu7564.BlockUpdate(input, 0, input.Length);
+ dstu7564.DoFinal(hash, 0);
- //test 4
- input = Hex.Decode("FF");
- expectedHash = Hex.Decode("871B18CF754B72740307A97B449ABEB32B64444CC0D5A4D65830AE5456837A72D8458F12C8F06C98C616ABE11897F86263B5CB77C420FB375374BEC52B6D0292");
- hash = new byte[hashBitSize / 8];
+ if (!Arrays.AreEqual(expectedHash, hash))
+ {
+ Fail("Failed hash-512 test 2 - expected "
+ + Hex.ToHexString(expectedHash)
+ + " got " + Hex.ToHexString(hash));
+ }
+ //test 3
+ input = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF");
+ expectedHash = Hex.Decode("0DD03D7350C409CB3C29C25893A0724F6B133FA8B9EB90A64D1A8FA93B56556611EB187D715A956B107E3BFC76482298133A9CE8CBC0BD5E1436A5B197284F7E");
+ hash = new byte[hashBitSize / 8];
- dstu7564 = new Dstu7564Digest(hashBitSize);
- dstu7564.BlockUpdate(input, 0, input.Length);
- dstu7564.DoFinal(hash, 0);
+ dstu7564 = new Dstu7564Digest(hashBitSize);
+ dstu7564.BlockUpdate(input, 0, input.Length);
+ dstu7564.DoFinal(hash, 0);
- if (!Arrays.AreEqual(expectedHash, hash))
- {
- Fail("Failed hash-512 test 4 - expected "
- + Hex.ToHexString(expectedHash)
- + " got " + Hex.ToHexString(hash));
- }
+ if (!Arrays.AreEqual(expectedHash, hash))
+ {
+ Fail("Failed hash-512 test 3 - expected "
+ + Hex.ToHexString(expectedHash)
+ + " got " + Hex.ToHexString(hash));
+ }
- //test 5
- input = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF");
- expectedHash = Hex.Decode("B189BFE987F682F5F167F0D7FA565330E126B6E592B1C55D44299064EF95B1A57F3C2D0ECF17869D1D199EBBD02E8857FB8ADD67A8C31F56CD82C016CF743121");
- hash = new byte[hashBitSize / 8];
+ //test 4
+ input = Hex.Decode("FF");
+ expectedHash = Hex.Decode("871B18CF754B72740307A97B449ABEB32B64444CC0D5A4D65830AE5456837A72D8458F12C8F06C98C616ABE11897F86263B5CB77C420FB375374BEC52B6D0292");
+ hash = new byte[hashBitSize / 8];
+ dstu7564 = new Dstu7564Digest(hashBitSize);
+ dstu7564.BlockUpdate(input, 0, input.Length);
+ dstu7564.DoFinal(hash, 0);
- dstu7564 = new Dstu7564Digest(hashBitSize);
- dstu7564.BlockUpdate(input, 0, input.Length);
- dstu7564.DoFinal(hash, 0);
+ if (!Arrays.AreEqual(expectedHash, hash))
+ {
+ Fail("Failed hash-512 test 4 - expected "
+ + Hex.ToHexString(expectedHash)
+ + " got " + Hex.ToHexString(hash));
+ }
- if (!Arrays.AreEqual(expectedHash, hash))
- {
- Fail("Failed hash-512 test 5 - expected "
- + Hex.ToHexString(expectedHash)
- + " got " + Hex.ToHexString(hash));
- }
+ //test 5
+ input = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF");
+ expectedHash = Hex.Decode("B189BFE987F682F5F167F0D7FA565330E126B6E592B1C55D44299064EF95B1A57F3C2D0ECF17869D1D199EBBD02E8857FB8ADD67A8C31F56CD82C016CF743121");
+ hash = new byte[hashBitSize / 8];
+ dstu7564 = new Dstu7564Digest(hashBitSize);
+ dstu7564.BlockUpdate(input, 0, input.Length);
+ dstu7564.DoFinal(hash, 0);
- //test 6
- input = Hex.Decode("");
- expectedHash = Hex.Decode("656B2F4CD71462388B64A37043EA55DBE445D452AECD46C3298343314EF04019BCFA3F04265A9857F91BE91FCE197096187CEDA78C9C1C021C294A0689198538");
- hash = new byte[hashBitSize / 8];
+ if (!Arrays.AreEqual(expectedHash, hash))
+ {
+ Fail("Failed hash-512 test 5 - expected "
+ + Hex.ToHexString(expectedHash)
+ + " got " + Hex.ToHexString(hash));
+ }
+ //test 6
+ input = Hex.Decode("");
+ expectedHash = Hex.Decode("656B2F4CD71462388B64A37043EA55DBE445D452AECD46C3298343314EF04019BCFA3F04265A9857F91BE91FCE197096187CEDA78C9C1C021C294A0689198538");
+ hash = new byte[hashBitSize / 8];
- dstu7564 = new Dstu7564Digest(hashBitSize);
- dstu7564.BlockUpdate(input, 0, input.Length);
- dstu7564.DoFinal(hash, 0);
+ dstu7564 = new Dstu7564Digest(hashBitSize);
+ dstu7564.BlockUpdate(input, 0, input.Length);
+ dstu7564.DoFinal(hash, 0);
- if (!Arrays.AreEqual(expectedHash, hash))
- {
- Fail("Failed hash-512 test 6 - expected "
- + Hex.ToHexString(expectedHash)
- + " got " + Hex.ToHexString(hash));
+ if (!Arrays.AreEqual(expectedHash, hash))
+ {
+ Fail("Failed hash-512 test 6 - expected "
+ + Hex.ToHexString(expectedHash)
+ + " got " + Hex.ToHexString(hash));
+ }
}
- }
-
- private void hash384Tests()
- {
- int hashBitSize = 384;
-
- //test 1
- byte[] input = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E");
- byte[] expectedHash = Hex.Decode("D9021692D84E5175735654846BA751E6D0ED0FAC36DFBC0841287DCB0B5584C75016C3DECC2A6E47C50B2F3811E351B8");
- byte[] hash = new byte[hashBitSize / 8];
-
-
- Dstu7564Digest dstu7564 = new Dstu7564Digest(hashBitSize);
- dstu7564.BlockUpdate(input, 0, input.Length);
- dstu7564.DoFinal(hash, 0);
-
- if (!Arrays.AreEqual(expectedHash, hash))
+ private void hash384Tests()
{
- Fail("Failed hash-384 test 1 - expected "
- + Hex.ToHexString(expectedHash)
- + " got " + Hex.ToHexString(hash));
- }
- }
+ int hashBitSize = 384;
- private void hash256Tests()
- {
+ //test 1
+ byte[] input = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E");
+ byte[] expectedHash = Hex.Decode("D9021692D84E5175735654846BA751E6D0ED0FAC36DFBC0841287DCB0B5584C75016C3DECC2A6E47C50B2F3811E351B8");
+ byte[] hash = new byte[hashBitSize / 8];
- int hashBitSize = 256;
+ Dstu7564Digest dstu7564 = new Dstu7564Digest(hashBitSize);
+ dstu7564.BlockUpdate(input, 0, input.Length);
+ dstu7564.DoFinal(hash, 0);
- //test 1
- byte[] input = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F");
- byte[] expectedHash = Hex.Decode("08F4EE6F1BE6903B324C4E27990CB24EF69DD58DBE84813EE0A52F6631239875");
- byte[] hash = new byte[hashBitSize / 8];
+ if (!Arrays.AreEqual(expectedHash, hash))
+ {
+ Fail("Failed hash-384 test 1 - expected "
+ + Hex.ToHexString(expectedHash)
+ + " got " + Hex.ToHexString(hash));
+ }
+ }
+ private void hash256Tests()
+ {
+ int hashBitSize = 256;
- Dstu7564Digest dstu7564 = new Dstu7564Digest(hashBitSize);
- dstu7564.BlockUpdate(input, 0, input.Length);
- dstu7564.DoFinal(hash, 0);
+ //test 1
+ byte[] input = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F");
+ byte[] expectedHash = Hex.Decode("08F4EE6F1BE6903B324C4E27990CB24EF69DD58DBE84813EE0A52F6631239875");
+ byte[] hash = new byte[hashBitSize / 8];
- if (!Arrays.AreEqual(expectedHash, hash))
- {
- Fail("Failed hash-256 test 1 - expected "
- + Hex.ToHexString(expectedHash)
- + " got " + Hex.ToHexString(hash));
- }
+ Dstu7564Digest dstu7564 = new Dstu7564Digest(hashBitSize);
+ dstu7564.BlockUpdate(input, 0, input.Length);
+ dstu7564.DoFinal(hash, 0);
- //test 2
- input = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F");
- expectedHash = Hex.Decode("0A9474E645A7D25E255E9E89FFF42EC7EB31349007059284F0B182E452BDA882");
- hash = new byte[hashBitSize / 8];
+ if (!Arrays.AreEqual(expectedHash, hash))
+ {
+ Fail("Failed hash-256 test 1 - expected "
+ + Hex.ToHexString(expectedHash)
+ + " got " + Hex.ToHexString(hash));
+ }
+ //test 2
+ input = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F");
+ expectedHash = Hex.Decode("0A9474E645A7D25E255E9E89FFF42EC7EB31349007059284F0B182E452BDA882");
+ hash = new byte[hashBitSize / 8];
- dstu7564 = new Dstu7564Digest(hashBitSize);
- dstu7564.BlockUpdate(input, 0, input.Length);
- dstu7564.DoFinal(hash, 0);
+ dstu7564 = new Dstu7564Digest(hashBitSize);
+ dstu7564.BlockUpdate(input, 0, input.Length);
+ dstu7564.DoFinal(hash, 0);
- if (!Arrays.AreEqual(expectedHash, hash))
- {
- Fail("Failed hash-256 test 2 - expected "
- + Hex.ToHexString(expectedHash)
- + " got " + Hex.ToHexString(hash));
- }
+ if (!Arrays.AreEqual(expectedHash, hash))
+ {
+ Fail("Failed hash-256 test 2 - expected "
+ + Hex.ToHexString(expectedHash)
+ + " got " + Hex.ToHexString(hash));
+ }
- //test 3
- input = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF");
- expectedHash = Hex.Decode("D305A32B963D149DC765F68594505D4077024F836C1BF03806E1624CE176C08F");
- hash = new byte[hashBitSize / 8];
+ //test 3
+ input = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF");
+ expectedHash = Hex.Decode("D305A32B963D149DC765F68594505D4077024F836C1BF03806E1624CE176C08F");
+ hash = new byte[hashBitSize / 8];
- dstu7564 = new Dstu7564Digest(hashBitSize);
- dstu7564.BlockUpdate(input, 0, input.Length);
- dstu7564.DoFinal(hash, 0);
+ dstu7564 = new Dstu7564Digest(hashBitSize);
+ dstu7564.BlockUpdate(input, 0, input.Length);
+ dstu7564.DoFinal(hash, 0);
- if (!Arrays.AreEqual(expectedHash, hash))
- {
- Fail("Failed hash-256 test 3 - expected "
- + Hex.ToHexString(expectedHash)
- + " got " + Hex.ToHexString(hash));
- }
+ if (!Arrays.AreEqual(expectedHash, hash))
+ {
+ Fail("Failed hash-256 test 3 - expected "
+ + Hex.ToHexString(expectedHash)
+ + " got " + Hex.ToHexString(hash));
+ }
- //test 4
- input = Hex.Decode("FF");
- expectedHash = Hex.Decode("EA7677CA4526555680441C117982EA14059EA6D0D7124D6ECDB3DEEC49E890F4");
- hash = new byte[hashBitSize / 8];
+ //test 4
+ input = Hex.Decode("FF");
+ expectedHash = Hex.Decode("EA7677CA4526555680441C117982EA14059EA6D0D7124D6ECDB3DEEC49E890F4");
+ hash = new byte[hashBitSize / 8];
- dstu7564 = new Dstu7564Digest(hashBitSize);
- dstu7564.BlockUpdate(input, 0, input.Length);
- dstu7564.DoFinal(hash, 0);
+ dstu7564 = new Dstu7564Digest(hashBitSize);
+ dstu7564.BlockUpdate(input, 0, input.Length);
+ dstu7564.DoFinal(hash, 0);
- if (!Arrays.AreEqual(expectedHash, hash))
- {
- Fail("Failed hash-256 test 4 - expected "
- + Hex.ToHexString(expectedHash)
- + " got " + Hex.ToHexString(hash));
- }
+ if (!Arrays.AreEqual(expectedHash, hash))
+ {
+ Fail("Failed hash-256 test 4 - expected "
+ + Hex.ToHexString(expectedHash)
+ + " got " + Hex.ToHexString(hash));
+ }
- //test 5
- input = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E");
- expectedHash = Hex.Decode("1075C8B0CB910F116BDA5FA1F19C29CF8ECC75CAFF7208BA2994B68FC56E8D16");
- hash = new byte[hashBitSize / 8];
+ //test 5
+ input = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E");
+ expectedHash = Hex.Decode("1075C8B0CB910F116BDA5FA1F19C29CF8ECC75CAFF7208BA2994B68FC56E8D16");
+ hash = new byte[hashBitSize / 8];
- dstu7564 = new Dstu7564Digest(hashBitSize);
- dstu7564.BlockUpdate(input, 0, input.Length);
- dstu7564.DoFinal(hash, 0);
+ dstu7564 = new Dstu7564Digest(hashBitSize);
+ dstu7564.BlockUpdate(input, 0, input.Length);
+ dstu7564.DoFinal(hash, 0);
- if (!Arrays.AreEqual(expectedHash, hash))
- {
- Fail("Failed hash-256 test 5 - expected "
- + Hex.ToHexString(expectedHash)
- + " got " + Hex.ToHexString(hash));
- }
+ if (!Arrays.AreEqual(expectedHash, hash))
+ {
+ Fail("Failed hash-256 test 5 - expected "
+ + Hex.ToHexString(expectedHash)
+ + " got " + Hex.ToHexString(hash));
+ }
- //test 6
- input = Hex.Decode("");
- expectedHash = Hex.Decode("CD5101D1CCDF0D1D1F4ADA56E888CD724CA1A0838A3521E7131D4FB78D0F5EB6");
- hash = new byte[hashBitSize / 8];
+ //test 6
+ input = Hex.Decode("");
+ expectedHash = Hex.Decode("CD5101D1CCDF0D1D1F4ADA56E888CD724CA1A0838A3521E7131D4FB78D0F5EB6");
+ hash = new byte[hashBitSize / 8];
- dstu7564 = new Dstu7564Digest(hashBitSize);
- dstu7564.BlockUpdate(input, 0, input.Length);
- dstu7564.DoFinal(hash, 0);
+ dstu7564 = new Dstu7564Digest(hashBitSize);
+ dstu7564.BlockUpdate(input, 0, input.Length);
+ dstu7564.DoFinal(hash, 0);
- if (!Arrays.AreEqual(expectedHash, hash))
- {
- Fail("Failed hash-256 test 6 - expected "
- + Hex.ToHexString(expectedHash)
- + " got " + Hex.ToHexString(hash));
+ if (!Arrays.AreEqual(expectedHash, hash))
+ {
+ Fail("Failed hash-256 test 6 - expected "
+ + Hex.ToHexString(expectedHash)
+ + " got " + Hex.ToHexString(hash));
+ }
}
- }
- protected override IDigest CloneDigest(IDigest digest)
+ protected override IDigest CloneDigest(IDigest digest)
{
return new Dstu7564Digest((Dstu7564Digest)digest);
}
- public static void MainOld(
- string[] args)
+ public static void MainOld(string[] args)
{
RunTest(new Dstu7564Test());
}
diff --git a/crypto/test/src/crypto/test/RegressionTest.cs b/crypto/test/src/crypto/test/RegressionTest.cs
index 60c9d0f8f..4f505c752 100644
--- a/crypto/test/src/crypto/test/RegressionTest.cs
+++ b/crypto/test/src/crypto/test/RegressionTest.cs
@@ -128,6 +128,9 @@ namespace Org.BouncyCastle.Crypto.Tests
new X931SignerTest(),
new KeccakDigestTest(),
new ShakeDigestTest(),
+ new SM2EngineTest(),
+ new SM2KeyExchangeTest(),
+ new SM2SignerTest(),
};
public static void MainOld(string[] args)
diff --git a/crypto/test/src/crypto/test/SM2EngineTest.cs b/crypto/test/src/crypto/test/SM2EngineTest.cs
new file mode 100644
index 000000000..8a1987d52
--- /dev/null
+++ b/crypto/test/src/crypto/test/SM2EngineTest.cs
@@ -0,0 +1,167 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+ [TestFixture]
+ public class SM2EngineTest
+ : SimpleTest
+ {
+ public override string Name
+ {
+ get { return "SM2Engine"; }
+ }
+
+ private void DoEngineTestFp()
+ {
+ BigInteger SM2_ECC_P = new BigInteger("8542D69E4C044F18E8B92435BF6FF7DE457283915C45517D722EDB8B08F1DFC3", 16);
+ BigInteger SM2_ECC_A = new BigInteger("787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498", 16);
+ BigInteger SM2_ECC_B = new BigInteger("63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A", 16);
+ BigInteger SM2_ECC_N = new BigInteger("8542D69E4C044F18E8B92435BF6FF7DD297720630485628D5AE74EE7C32E79B7", 16);
+ BigInteger SM2_ECC_GX = new BigInteger("421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D", 16);
+ BigInteger SM2_ECC_GY = new BigInteger("0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2", 16);
+
+ ECCurve curve = new FpCurve(SM2_ECC_P, SM2_ECC_A, SM2_ECC_B);
+
+ ECPoint g = curve.CreatePoint(SM2_ECC_GX, SM2_ECC_GY);
+ ECDomainParameters domainParams = new ECDomainParameters(curve, g, SM2_ECC_N);
+
+ ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();
+
+ ECKeyGenerationParameters aKeyGenParams = new ECKeyGenerationParameters(domainParams, new TestRandomBigInteger("1649AB77A00637BD5E2EFE283FBF353534AA7F7CB89463F208DDBC2920BB0DA0", 16));
+
+ keyPairGenerator.Init(aKeyGenParams);
+
+ AsymmetricCipherKeyPair aKp = keyPairGenerator.GenerateKeyPair();
+
+ ECPublicKeyParameters aPub = (ECPublicKeyParameters)aKp.Public;
+ ECPrivateKeyParameters aPriv = (ECPrivateKeyParameters)aKp.Private;
+
+ SM2Engine sm2Engine = new SM2Engine();
+
+ byte[] m = Strings.ToByteArray("encryption standard");
+
+ sm2Engine.Init(true, new ParametersWithRandom(aPub, new TestRandomBigInteger("4C62EEFD6ECFC2B95B92FD6C3D9575148AFA17425546D49018E5388D49DD7B4F", 16)));
+
+ byte[] enc = sm2Engine.ProcessBlock(m, 0, m.Length);
+
+ IsTrue("enc wrong", Arrays.AreEqual(Hex.Decode(
+ "04245C26 FB68B1DD DDB12C4B 6BF9F2B6 D5FE60A3 83B0D18D 1C4144AB F17F6252" +
+ "E776CB92 64C2A7E8 8E52B199 03FDC473 78F605E3 6811F5C0 7423A24B 84400F01" +
+ "B8650053 A89B41C4 18B0C3AA D00D886C 00286467 9C3D7360 C30156FA B7C80A02" +
+ "76712DA9 D8094A63 4B766D3A 285E0748 0653426D"), enc));
+
+ sm2Engine.Init(false, aPriv);
+
+ byte[] dec = sm2Engine.ProcessBlock(enc, 0, enc.Length);
+
+ IsTrue("dec wrong", Arrays.AreEqual(m, dec));
+
+ enc[80] = (byte)(enc[80] + 1);
+
+ try
+ {
+ sm2Engine.ProcessBlock(enc, 0, enc.Length);
+ Fail("no exception");
+ }
+ catch (InvalidCipherTextException e)
+ {
+ IsTrue("wrong exception", "invalid cipher text".Equals(e.Message));
+ }
+
+ // long message
+ sm2Engine = new SM2Engine();
+
+ m = new byte[4097];
+ for (int i = 0; i != m.Length; i++)
+ {
+ m[i] = (byte)i;
+ }
+
+ sm2Engine.Init(true, new ParametersWithRandom(aPub, new TestRandomBigInteger("4C62EEFD6ECFC2B95B92FD6C3D9575148AFA17425546D49018E5388D49DD7B4F", 16)));
+
+ enc = sm2Engine.ProcessBlock(m, 0, m.Length);
+
+ sm2Engine.Init(false, aPriv);
+
+ dec = sm2Engine.ProcessBlock(enc, 0, enc.Length);
+
+ IsTrue("dec wrong", Arrays.AreEqual(m, dec));
+ }
+
+ private void DoEngineTestF2m()
+ {
+ BigInteger SM2_ECC_A = new BigInteger("00", 16);
+ BigInteger SM2_ECC_B = new BigInteger("E78BCD09746C202378A7E72B12BCE00266B9627ECB0B5A25367AD1AD4CC6242B", 16);
+ BigInteger SM2_ECC_N = new BigInteger("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBC972CF7E6B6F900945B3C6A0CF6161D", 16);
+ BigInteger SM2_ECC_GX = new BigInteger("00CDB9CA7F1E6B0441F658343F4B10297C0EF9B6491082400A62E7A7485735FADD", 16);
+ BigInteger SM2_ECC_GY = new BigInteger("013DE74DA65951C4D76DC89220D5F7777A611B1C38BAE260B175951DC8060C2B3E", 16);
+ BigInteger SM2_ECC_H = BigInteger.ValueOf(4);
+
+ ECCurve curve = new F2mCurve(257, 12, SM2_ECC_A, SM2_ECC_B);
+
+ ECPoint g = curve.CreatePoint(SM2_ECC_GX, SM2_ECC_GY);
+ ECDomainParameters domainParams = new ECDomainParameters(curve, g, SM2_ECC_N, SM2_ECC_H);
+
+ ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();
+
+ ECKeyGenerationParameters aKeyGenParams = new ECKeyGenerationParameters(domainParams, new TestRandomBigInteger("56A270D17377AA9A367CFA82E46FA5267713A9B91101D0777B07FCE018C757EB", 16));
+
+ keyPairGenerator.Init(aKeyGenParams);
+
+ AsymmetricCipherKeyPair aKp = keyPairGenerator.GenerateKeyPair();
+
+ ECPublicKeyParameters aPub = (ECPublicKeyParameters)aKp.Public;
+ ECPrivateKeyParameters aPriv = (ECPrivateKeyParameters)aKp.Private;
+
+ SM2Engine sm2Engine = new SM2Engine();
+
+ byte[] m = Strings.ToByteArray("encryption standard");
+
+ sm2Engine.Init(true, new ParametersWithRandom(aPub, new TestRandomBigInteger("6D3B497153E3E92524E5C122682DBDC8705062E20B917A5F8FCDB8EE4C66663D", 16)));
+
+ byte[] enc = sm2Engine.ProcessBlock(m, 0, m.Length);
+
+ IsTrue("f2m enc wrong", Arrays.AreEqual(Hex.Decode(
+ "04019D23 6DDB3050 09AD52C5 1BB93270 9BD534D4 76FBB7B0 DF9542A8 A4D890A3" +
+ "F2E100B2 3B938DC0 A94D1DF8 F42CF45D 2D6601BF 638C3D7D E75A29F0 2AFB7E45" +
+ "E91771FD 55AC6213 C2A8A040 E4CAB5B2 6A9CFCDA 737373A4 8625D375 8FA37B3E" +
+ "AB80E9CF CABA665E 3199EA15 A1FA8189 D96F5791 25E4"), enc));
+
+ sm2Engine.Init(false, aPriv);
+
+ byte[] dec = sm2Engine.ProcessBlock(enc, 0, enc.Length);
+
+ IsTrue("f2m dec wrong", Arrays.AreEqual(m, dec));
+ }
+
+ public override void PerformTest()
+ {
+ DoEngineTestFp();
+ DoEngineTestF2m();
+ }
+
+ public static void Main(string[] args)
+ {
+ RunTest(new SM2EngineTest());
+ }
+
+ [Test]
+ public void TestFunction()
+ {
+ string resultText = Perform().ToString();
+
+ Assert.AreEqual(Name + ": Okay", resultText);
+ }
+ }
+}
diff --git a/crypto/test/src/crypto/test/SM2KeyExchangeTest.cs b/crypto/test/src/crypto/test/SM2KeyExchangeTest.cs
new file mode 100644
index 000000000..d7a2650eb
--- /dev/null
+++ b/crypto/test/src/crypto/test/SM2KeyExchangeTest.cs
@@ -0,0 +1,229 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Crypto.Agreement;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+ [TestFixture]
+ public class SM2KeyExchangeTest
+ : SimpleTest
+ {
+ public override string Name
+ {
+ get { return "SM2KeyExchange"; }
+ }
+
+ private void DoKeyExchangeTestFp()
+ {
+ BigInteger SM2_ECC_P = new BigInteger("8542D69E4C044F18E8B92435BF6FF7DE457283915C45517D722EDB8B08F1DFC3", 16);
+ BigInteger SM2_ECC_A = new BigInteger("787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498", 16);
+ BigInteger SM2_ECC_B = new BigInteger("63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A", 16);
+ BigInteger SM2_ECC_N = new BigInteger("8542D69E4C044F18E8B92435BF6FF7DD297720630485628D5AE74EE7C32E79B7", 16);
+ BigInteger SM2_ECC_GX = new BigInteger("421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D", 16);
+ BigInteger SM2_ECC_GY = new BigInteger("0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2", 16);
+
+ ECCurve curve = new FpCurve(SM2_ECC_P, SM2_ECC_A, SM2_ECC_B);
+
+ ECPoint g = curve.CreatePoint(SM2_ECC_GX, SM2_ECC_GY);
+ ECDomainParameters domainParams = new ECDomainParameters(curve, g, SM2_ECC_N);
+
+ ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();
+
+ ECKeyGenerationParameters aKeyGenParams = new ECKeyGenerationParameters(domainParams, new TestRandomBigInteger("6FCBA2EF9AE0AB902BC3BDE3FF915D44BA4CC78F88E2F8E7F8996D3B8CCEEDEE", 16));
+
+ keyPairGenerator.Init(aKeyGenParams);
+
+ AsymmetricCipherKeyPair aKp = keyPairGenerator.GenerateKeyPair();
+
+ ECPublicKeyParameters aPub = (ECPublicKeyParameters)aKp.Public;
+ ECPrivateKeyParameters aPriv = (ECPrivateKeyParameters)aKp.Private;
+
+ ECKeyGenerationParameters aeKeyGenParams = new ECKeyGenerationParameters(domainParams, new TestRandomBigInteger("83A2C9C8B96E5AF70BD480B472409A9A327257F1EBB73F5B073354B248668563", 16));
+
+ keyPairGenerator.Init(aeKeyGenParams);
+
+ AsymmetricCipherKeyPair aeKp = keyPairGenerator.GenerateKeyPair();
+
+ ECPublicKeyParameters aePub = (ECPublicKeyParameters)aeKp.Public;
+ ECPrivateKeyParameters aePriv = (ECPrivateKeyParameters)aeKp.Private;
+
+ ECKeyGenerationParameters bKeyGenParams = new ECKeyGenerationParameters(domainParams, new TestRandomBigInteger("5E35D7D3F3C54DBAC72E61819E730B019A84208CA3A35E4C2E353DFCCB2A3B53", 16));
+
+ keyPairGenerator.Init(bKeyGenParams);
+
+ AsymmetricCipherKeyPair bKp = keyPairGenerator.GenerateKeyPair();
+
+ ECPublicKeyParameters bPub = (ECPublicKeyParameters)bKp.Public;
+ ECPrivateKeyParameters bPriv = (ECPrivateKeyParameters)bKp.Private;
+
+ ECKeyGenerationParameters beKeyGenParams = new ECKeyGenerationParameters(domainParams, new TestRandomBigInteger("33FE21940342161C55619C4A0C060293D543C80AF19748CE176D83477DE71C80", 16));
+
+ keyPairGenerator.Init(beKeyGenParams);
+
+ AsymmetricCipherKeyPair beKp = keyPairGenerator.GenerateKeyPair();
+
+ ECPublicKeyParameters bePub = (ECPublicKeyParameters)beKp.Public;
+ ECPrivateKeyParameters bePriv = (ECPrivateKeyParameters)beKp.Private;
+
+ SM2KeyExchange exch = new SM2KeyExchange();
+
+ exch.Init(new ParametersWithID(new SM2KeyExchangePrivateParameters(true, aPriv, aePriv), Strings.ToByteArray("ALICE123@YAHOO.COM")));
+
+ byte[] k1 = exch.CalculateKey(128, new ParametersWithID(new SM2KeyExchangePublicParameters(bPub, bePub), Strings.ToByteArray("BILL456@YAHOO.COM")));
+
+ IsTrue("key 1 wrong", Arrays.AreEqual(Hex.Decode("55b0ac62a6b927ba23703832c853ded4"), k1));
+
+ exch = new SM2KeyExchange();
+
+ exch.Init(new ParametersWithID(new SM2KeyExchangePrivateParameters(false, bPriv, bePriv), Strings.ToByteArray("BILL456@YAHOO.COM")));
+
+ byte[] k2 = exch.CalculateKey(128, new ParametersWithID(new SM2KeyExchangePublicParameters(aPub, aePub), Strings.ToByteArray("ALICE123@YAHOO.COM")));
+
+ IsTrue("key 2 wrong", Arrays.AreEqual(Hex.Decode("55b0ac62a6b927ba23703832c853ded4"), k2));
+
+ // with key confirmation
+ exch = new SM2KeyExchange();
+
+ exch.Init(new ParametersWithID(new SM2KeyExchangePrivateParameters(false, bPriv, bePriv), Strings.ToByteArray("BILL456@YAHOO.COM")));
+
+ byte[][] vals2 = exch.CalculateKeyWithConfirmation(128, null, new ParametersWithID(new SM2KeyExchangePublicParameters(aPub, aePub), Strings.ToByteArray("ALICE123@YAHOO.COM")));
+
+ IsTrue("key 2 wrong", Arrays.AreEqual(Hex.Decode("55b0ac62a6b927ba23703832c853ded4"), k2));
+
+ IsTrue("conf a tag 2 wrong", Arrays.AreEqual(Hex.Decode("284C8F198F141B502E81250F1581C7E9EEB4CA6990F9E02DF388B45471F5BC5C"), vals2[1]));
+ IsTrue("conf b tag 2 wrong", Arrays.AreEqual(Hex.Decode("23444DAF8ED7534366CB901C84B3BDBB63504F4065C1116C91A4C00697E6CF7A"), vals2[2]));
+
+ exch = new SM2KeyExchange();
+
+ exch.Init(new ParametersWithID(new SM2KeyExchangePrivateParameters(true, aPriv, aePriv), Strings.ToByteArray("ALICE123@YAHOO.COM")));
+
+ byte[][] vals1 = exch.CalculateKeyWithConfirmation(128, vals2[1], new ParametersWithID(new SM2KeyExchangePublicParameters(bPub, bePub), Strings.ToByteArray("BILL456@YAHOO.COM")));
+
+ IsTrue("conf key 1 wrong", Arrays.AreEqual(Hex.Decode("55b0ac62a6b927ba23703832c853ded4"), vals1[0]));
+ IsTrue("conf tag 1 wrong", Arrays.AreEqual(Hex.Decode("23444DAF8ED7534366CB901C84B3BDBB63504F4065C1116C91A4C00697E6CF7A"), vals1[1]));
+ }
+
+ private void DoKeyExchangeTestF2m()
+ {
+ BigInteger SM2_ECC_A = new BigInteger("00", 16);
+ BigInteger SM2_ECC_B = new BigInteger("E78BCD09746C202378A7E72B12BCE00266B9627ECB0B5A25367AD1AD4CC6242B", 16);
+ BigInteger SM2_ECC_N = new BigInteger("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBC972CF7E6B6F900945B3C6A0CF6161D", 16);
+ BigInteger SM2_ECC_GX = new BigInteger("00CDB9CA7F1E6B0441F658343F4B10297C0EF9B6491082400A62E7A7485735FADD", 16);
+ BigInteger SM2_ECC_GY = new BigInteger("013DE74DA65951C4D76DC89220D5F7777A611B1C38BAE260B175951DC8060C2B3E", 16);
+ BigInteger SM2_ECC_H = BigInteger.ValueOf(4);
+
+ ECCurve curve = new F2mCurve(257, 12, SM2_ECC_A, SM2_ECC_B);
+
+ ECPoint g = curve.CreatePoint(SM2_ECC_GX, SM2_ECC_GY);
+ ECDomainParameters domainParams = new ECDomainParameters(curve, g, SM2_ECC_N, SM2_ECC_H);
+
+ ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();
+
+ ECKeyGenerationParameters aKeyGenParams = new ECKeyGenerationParameters(domainParams, new TestRandomBigInteger("4813903D254F2C20A94BC5704238496954BB5279F861952EF2C5298E84D2CEAA", 16));
+
+ keyPairGenerator.Init(aKeyGenParams);
+
+ AsymmetricCipherKeyPair aKp = keyPairGenerator.GenerateKeyPair();
+
+ ECPublicKeyParameters aPub = (ECPublicKeyParameters)aKp.Public;
+ ECPrivateKeyParameters aPriv = (ECPrivateKeyParameters)aKp.Private;
+
+ ECKeyGenerationParameters aeKeyGenParams = new ECKeyGenerationParameters(domainParams, new TestRandomBigInteger("54A3D6673FF3A6BD6B02EBB164C2A3AF6D4A4906229D9BFCE68CC366A2E64BA4", 16));
+
+ keyPairGenerator.Init(aeKeyGenParams);
+
+ AsymmetricCipherKeyPair aeKp = keyPairGenerator.GenerateKeyPair();
+
+ ECPublicKeyParameters aePub = (ECPublicKeyParameters)aeKp.Public;
+ ECPrivateKeyParameters aePriv = (ECPrivateKeyParameters)aeKp.Private;
+
+ ECKeyGenerationParameters bKeyGenParams = new ECKeyGenerationParameters(domainParams, new TestRandomBigInteger("08F41BAE0922F47C212803FE681AD52B9BF28A35E1CD0EC273A2CF813E8FD1DC", 16));
+
+ keyPairGenerator.Init(bKeyGenParams);
+
+ AsymmetricCipherKeyPair bKp = keyPairGenerator.GenerateKeyPair();
+
+ ECPublicKeyParameters bPub = (ECPublicKeyParameters)bKp.Public;
+ ECPrivateKeyParameters bPriv = (ECPrivateKeyParameters)bKp.Private;
+
+ ECKeyGenerationParameters beKeyGenParams = new ECKeyGenerationParameters(domainParams, new TestRandomBigInteger("1F21933387BEF781D0A8F7FD708C5AE0A56EE3F423DBC2FE5BDF6F068C53F7AD", 16));
+
+ keyPairGenerator.Init(beKeyGenParams);
+
+ AsymmetricCipherKeyPair beKp = keyPairGenerator.GenerateKeyPair();
+
+ ECPublicKeyParameters bePub = (ECPublicKeyParameters)beKp.Public;
+ ECPrivateKeyParameters bePriv = (ECPrivateKeyParameters)beKp.Private;
+
+ SM2KeyExchange exch = new SM2KeyExchange();
+
+ exch.Init(new ParametersWithID(new SM2KeyExchangePrivateParameters(true, aPriv, aePriv), Strings.ToByteArray("ALICE123@YAHOO.COM")));
+
+ byte[] k1 = exch.CalculateKey(128, new ParametersWithID(new SM2KeyExchangePublicParameters(bPub, bePub), Strings.ToByteArray("BILL456@YAHOO.COM")));
+
+ // there appears to be typo for ZA in the draft
+ //IsTrue("F2m key 1 wrong", Arrays.AreEqual(Hex.Decode("4E587E5C66634F22D973A7D98BF8BE23"), k1));
+ IsTrue("F2m key 1 wrong", Arrays.AreEqual(Hex.Decode("8c2b03289aa7126555dc660cfc29fd74"), k1));
+
+ exch = new SM2KeyExchange();
+
+ exch.Init(new ParametersWithID(new SM2KeyExchangePrivateParameters(false, bPriv, bePriv), Strings.ToByteArray("BILL456@YAHOO.COM")));
+
+ byte[] k2 = exch.CalculateKey(128, new ParametersWithID(new SM2KeyExchangePublicParameters(aPub, aePub), Strings.ToByteArray("ALICE123@YAHOO.COM")));
+
+ //IsTrue("F2m key 2 wrong", Arrays.AreEqual(Hex.Decode("4E587E5C66634F22D973A7D98BF8BE23"), k2));
+ IsTrue("F2m key 2 wrong", Arrays.AreEqual(Hex.Decode("8c2b03289aa7126555dc660cfc29fd74"), k2));
+
+ // with key confirmation
+ exch = new SM2KeyExchange();
+
+ exch.Init(new ParametersWithID(new SM2KeyExchangePrivateParameters(false, bPriv, bePriv), Strings.ToByteArray("BILL456@YAHOO.COM")));
+
+ byte[][] vals2 = exch.CalculateKeyWithConfirmation(128, null, new ParametersWithID(new SM2KeyExchangePublicParameters(aPub, aePub), Strings.ToByteArray("ALICE123@YAHOO.COM")));
+
+ IsTrue("key 2 wrong", Arrays.AreEqual(Hex.Decode("8c2b03289aa7126555dc660cfc29fd74"), k2));
+
+ IsTrue("conf a tag 2 wrong", Arrays.AreEqual(Hex.Decode("d8294c4c0f0ac180feac95e8a0d786638c9e915b9a684b2348809af03a0de2a5"), vals2[1]));
+ IsTrue("conf b tag 2 wrong", Arrays.AreEqual(Hex.Decode("52089e706911b58fd5e7c7b2ab5cf32bb61e481ef1e114a1e33d99eec84b5a4f"), vals2[2]));
+
+ exch = new SM2KeyExchange();
+
+ exch.Init(new ParametersWithID(new SM2KeyExchangePrivateParameters(true, aPriv, aePriv), Strings.ToByteArray("ALICE123@YAHOO.COM")));
+
+ byte[][] vals1 = exch.CalculateKeyWithConfirmation(128, vals2[1], new ParametersWithID(new SM2KeyExchangePublicParameters(bPub, bePub), Strings.ToByteArray("BILL456@YAHOO.COM")));
+
+ IsTrue("conf key 1 wrong", Arrays.AreEqual(Hex.Decode("8c2b03289aa7126555dc660cfc29fd74"), vals1[0]));
+ IsTrue("conf tag 1 wrong", Arrays.AreEqual(Hex.Decode("52089e706911b58fd5e7c7b2ab5cf32bb61e481ef1e114a1e33d99eec84b5a4f"), vals1[1]));
+ }
+
+ public override void PerformTest()
+ {
+ DoKeyExchangeTestFp();
+ DoKeyExchangeTestF2m();
+ }
+
+ public static void Main(string[] args)
+ {
+ RunTest(new SM2KeyExchangeTest());
+ }
+
+ [Test]
+ public void TestFunction()
+ {
+ string resultText = Perform().ToString();
+
+ Assert.AreEqual(Name + ": Okay", resultText);
+ }
+ }
+}
diff --git a/crypto/test/src/crypto/test/SM2SignerTest.cs b/crypto/test/src/crypto/test/SM2SignerTest.cs
new file mode 100644
index 000000000..5904c95a7
--- /dev/null
+++ b/crypto/test/src/crypto/test/SM2SignerTest.cs
@@ -0,0 +1,193 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Signers;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+ [TestFixture]
+ public class SM2SignerTest
+ : SimpleTest
+ {
+ public override string Name
+ {
+ get { return "SM2Signer"; }
+ }
+
+ private void DoSignerTestFp()
+ {
+ BigInteger SM2_ECC_P = new BigInteger("8542D69E4C044F18E8B92435BF6FF7DE457283915C45517D722EDB8B08F1DFC3", 16);
+ BigInteger SM2_ECC_A = new BigInteger("787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498", 16);
+ BigInteger SM2_ECC_B = new BigInteger("63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A", 16);
+ BigInteger SM2_ECC_N = new BigInteger("8542D69E4C044F18E8B92435BF6FF7DD297720630485628D5AE74EE7C32E79B7", 16);
+ BigInteger SM2_ECC_GX = new BigInteger("421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D", 16);
+ BigInteger SM2_ECC_GY = new BigInteger("0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2", 16);
+
+ ECCurve curve = new FpCurve(SM2_ECC_P, SM2_ECC_A, SM2_ECC_B);
+
+ ECPoint g = curve.CreatePoint(SM2_ECC_GX, SM2_ECC_GY);
+ ECDomainParameters domainParams = new ECDomainParameters(curve, g, SM2_ECC_N);
+
+ ECKeyGenerationParameters keyGenerationParams = new ECKeyGenerationParameters(domainParams, new TestRandomBigInteger("128B2FA8BD433C6C068C8D803DFF79792A519A55171B1B650C23661D15897263", 16));
+ ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();
+
+ keyPairGenerator.Init(keyGenerationParams);
+ AsymmetricCipherKeyPair kp = keyPairGenerator.GenerateKeyPair();
+
+ ECPublicKeyParameters ecPub = (ECPublicKeyParameters)kp.Public;
+ ECPrivateKeyParameters ecPriv = (ECPrivateKeyParameters)kp.Private;
+
+ SM2Signer signer = new SM2Signer();
+
+ signer.Init(true,
+ new ParametersWithID(new ParametersWithRandom(ecPriv,
+ new TestRandomBigInteger("6CB28D99385C175C94F94E934817663FC176D925DD72B727260DBAAE1FB2F96F", 16)),
+ Strings.ToByteArray("ALICE123@YAHOO.COM")));
+
+ byte[] msg = Strings.ToByteArray("message digest");
+
+ signer.BlockUpdate(msg, 0, msg.Length);
+
+ byte[] sig = signer.GenerateSignature();
+
+ BigInteger[] rs = Decode(sig);
+
+ IsTrue("r wrong", rs[0].Equals(new BigInteger("40F1EC59F793D9F49E09DCEF49130D4194F79FB1EED2CAA55BACDB49C4E755D1", 16)));
+ IsTrue("s wrong", rs[1].Equals(new BigInteger("6FC6DAC32C5D5CF10C77DFB20F7C2EB667A457872FB09EC56327A67EC7DEEBE7", 16)));
+
+ signer.Init(false, new ParametersWithID(ecPub, Strings.ToByteArray("ALICE123@YAHOO.COM")));
+
+ signer.BlockUpdate(msg, 0, msg.Length);
+
+ IsTrue("verification failed", signer.VerifySignature(sig));
+ }
+
+ private void DoSignerTestF2m()
+ {
+ BigInteger SM2_ECC_A = new BigInteger("00", 16);
+ BigInteger SM2_ECC_B = new BigInteger("E78BCD09746C202378A7E72B12BCE00266B9627ECB0B5A25367AD1AD4CC6242B", 16);
+ BigInteger SM2_ECC_N = new BigInteger("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBC972CF7E6B6F900945B3C6A0CF6161D", 16);
+ BigInteger SM2_ECC_GX = new BigInteger("00CDB9CA7F1E6B0441F658343F4B10297C0EF9B6491082400A62E7A7485735FADD", 16);
+ BigInteger SM2_ECC_GY = new BigInteger("013DE74DA65951C4D76DC89220D5F7777A611B1C38BAE260B175951DC8060C2B3E", 16);
+
+ ECCurve curve = new F2mCurve(257, 12, SM2_ECC_A, SM2_ECC_B);
+
+ ECPoint g = curve.CreatePoint(SM2_ECC_GX, SM2_ECC_GY);
+ ECDomainParameters domainParams = new ECDomainParameters(curve, g, SM2_ECC_N);
+
+ ECKeyGenerationParameters keyGenerationParams = new ECKeyGenerationParameters(domainParams, new TestRandomBigInteger("771EF3DBFF5F1CDC32B9C572930476191998B2BF7CB981D7F5B39202645F0931", 16));
+ ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();
+
+ keyPairGenerator.Init(keyGenerationParams);
+ AsymmetricCipherKeyPair kp = keyPairGenerator.GenerateKeyPair();
+
+ ECPublicKeyParameters ecPub = (ECPublicKeyParameters)kp.Public;
+ ECPrivateKeyParameters ecPriv = (ECPrivateKeyParameters)kp.Private;
+
+ SM2Signer signer = new SM2Signer();
+
+ signer.Init(true,
+ new ParametersWithID(new ParametersWithRandom(ecPriv,
+ new TestRandomBigInteger("36CD79FC8E24B7357A8A7B4A46D454C397703D6498158C605399B341ADA186D6", 16)),
+ Strings.ToByteArray("ALICE123@YAHOO.COM")));
+
+ byte[] msg = Strings.ToByteArray("message digest");
+
+ signer.BlockUpdate(msg, 0, msg.Length);
+
+ byte[] sig = signer.GenerateSignature();
+
+ BigInteger[] rs = Decode(sig);
+
+ IsTrue("F2m r wrong", rs[0].Equals(new BigInteger("6D3FBA26EAB2A1054F5D198332E335817C8AC453ED26D3391CD4439D825BF25B", 16)));
+ IsTrue("F2m s wrong", rs[1].Equals(new BigInteger("3124C5688D95F0A10252A9BED033BEC84439DA384621B6D6FAD77F94B74A9556", 16)));
+
+ signer.Init(false, new ParametersWithID(ecPub, Strings.ToByteArray("ALICE123@YAHOO.COM")));
+
+ signer.BlockUpdate(msg, 0, msg.Length);
+
+ IsTrue("verification failed", signer.VerifySignature(sig));
+ }
+
+ private void DoVerifyBoundsCheck()
+ {
+ BigInteger SM2_ECC_A = new BigInteger("00", 16);
+ BigInteger SM2_ECC_B = new BigInteger("E78BCD09746C202378A7E72B12BCE00266B9627ECB0B5A25367AD1AD4CC6242B", 16);
+ BigInteger SM2_ECC_N = new BigInteger("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBC972CF7E6B6F900945B3C6A0CF6161D", 16);
+ BigInteger SM2_ECC_GX = new BigInteger("00CDB9CA7F1E6B0441F658343F4B10297C0EF9B6491082400A62E7A7485735FADD", 16);
+ BigInteger SM2_ECC_GY = new BigInteger("013DE74DA65951C4D76DC89220D5F7777A611B1C38BAE260B175951DC8060C2B3E", 16);
+
+ ECCurve curve = new F2mCurve(257, 12, SM2_ECC_A, SM2_ECC_B);
+
+ ECPoint g = curve.CreatePoint(SM2_ECC_GX, SM2_ECC_GY);
+ ECDomainParameters domainParams = new ECDomainParameters(curve, g, SM2_ECC_N);
+
+ ECKeyGenerationParameters keyGenerationParams = new ECKeyGenerationParameters(domainParams, new TestRandomBigInteger("771EF3DBFF5F1CDC32B9C572930476191998B2BF7CB981D7F5B39202645F0931", 16));
+ ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();
+
+ keyPairGenerator.Init(keyGenerationParams);
+ AsymmetricCipherKeyPair kp = keyPairGenerator.GenerateKeyPair();
+
+ ECPublicKeyParameters ecPub = (ECPublicKeyParameters)kp.Public;
+
+ SM2Signer signer = new SM2Signer();
+
+ signer.Init(false, ecPub);
+
+ signer.BlockUpdate(new byte[20], 0, 20);
+ IsTrue(!signer.VerifySignature(Encode(BigInteger.Zero, BigInteger.ValueOf(8))));
+
+ signer.BlockUpdate(new byte[20], 0, 20);
+ IsTrue(!signer.VerifySignature(Encode(BigInteger.ValueOf(8), BigInteger.Zero)));
+
+ signer.BlockUpdate(new byte[20], 0, 20);
+ IsTrue(!signer.VerifySignature(Encode(SM2_ECC_N, BigInteger.ValueOf(8))));
+
+ signer.BlockUpdate(new byte[20], 0, 20);
+ IsTrue(!signer.VerifySignature(Encode(BigInteger.ValueOf(8), SM2_ECC_N)));
+ }
+
+ public override void PerformTest()
+ {
+ DoSignerTestFp();
+ DoSignerTestF2m();
+ DoVerifyBoundsCheck();
+ }
+
+ private static BigInteger[] Decode(byte[] sig)
+ {
+ Asn1Sequence s = Asn1Sequence.GetInstance(sig);
+
+ return new BigInteger[] { DerInteger.GetInstance(s[0]).Value,
+ DerInteger.GetInstance(s[1]).Value };
+ }
+
+ private static byte[] Encode(BigInteger r, BigInteger s)
+ {
+ return new DerSequence(new DerInteger(r), new DerInteger(s)).GetEncoded();
+ }
+
+ public static void Main(
+ string[] args)
+ {
+ RunTest(new SM2SignerTest());
+ }
+
+ [Test]
+ public void TestFunction()
+ {
+ string resultText = Perform().ToString();
+
+ Assert.AreEqual(Name + ": Okay", resultText);
+ }
+ }
+}
diff --git a/crypto/test/src/crypto/test/SM3DigestTest.cs b/crypto/test/src/crypto/test/SM3DigestTest.cs
index c8b8f2ec9..41aa2cd62 100644
--- a/crypto/test/src/crypto/test/SM3DigestTest.cs
+++ b/crypto/test/src/crypto/test/SM3DigestTest.cs
@@ -2,10 +2,8 @@ using System;
using NUnit.Framework;
-using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Utilities.Encoders;
-using Org.BouncyCastle.Utilities.Test;
namespace Org.BouncyCastle.Crypto.Tests
{
@@ -26,7 +24,109 @@ namespace Org.BouncyCastle.Crypto.Tests
"abcdefghijklmnopqrstuvwxyz",
};
- private static string[] digests = {
+ private static string[] hexMessages = {
+ /* 2 p.57 ZA */
+ "0090" +
+ "414C494345313233405941484F4F2E434F4D" +
+ "787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498" +
+ "63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A" +
+ "421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D" +
+ "0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2" +
+ "0AE4C7798AA0F119471BEE11825BE46202BB79E2A5844495E97C04FF4DF2548A" +
+ "7C0240F88F1CD4E16352A73C17B7F16F07353E53A176D684A9FE0C6BB798E857",
+ /* 3 p.59 ZA */
+ "0090" +
+ "414C494345313233405941484F4F2E434F4D" +
+ "000000000000000000000000000000000000000000000000000000000000000000" +
+ "00E78BCD09746C202378A7E72B12BCE00266B9627ECB0B5A25367AD1AD4CC6242B" +
+ "00CDB9CA7F1E6B0441F658343F4B10297C0EF9B6491082400A62E7A7485735FADD" +
+ "013DE74DA65951C4D76DC89220D5F7777A611B1C38BAE260B175951DC8060C2B3E" +
+ "0165961645281A8626607B917F657D7E9382F1EA5CD931F40F6627F357542653B2" +
+ "01686522130D590FB8DE635D8FCA715CC6BF3D05BEF3F75DA5D543454448166612",
+ /* 4 p.72 ZA */
+ "0090" +
+ "414C494345313233405941484F4F2E434F4D" +
+ "787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498" +
+ "63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A" +
+ "421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D" +
+ "0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2" +
+ "3099093BF3C137D8FCBBCDF4A2AE50F3B0F216C3122D79425FE03A45DBFE1655" +
+ "3DF79E8DAC1CF0ECBAA2F2B49D51A4B387F2EFAF482339086A27A8E05BAED98B",
+ /* 5 p.72 ZB */
+ "0088" +
+ "42494C4C343536405941484F4F2E434F4D" +
+ "787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498" +
+ "63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A" +
+ "421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D" +
+ "0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2" +
+ "245493D446C38D8CC0F118374690E7DF633A8A4BFB3329B5ECE604B2B4F37F43" +
+ "53C0869F4B9E17773DE68FEC45E14904E0DEA45BF6CECF9918C85EA047C60A4C",
+ /* 6 p.75 ZA */
+ "0090" +
+ "414C494345313233405941484F4F2E434F4D" +
+ "000000000000000000000000000000000000000000000000000000000000000000" +
+ "00E78BCD09746C202378A7E72B12BCE00266B9627ECB0B5A25367AD1AD4CC6242B" +
+ "00CDB9CA7F1E6B0441F658343F4B10297C0EF9B6491082400A62E7A7485735FADD" +
+ "013DE74DA65951C4D76DC89220D5F7777A611B1C38BAE260B175951DC8060C2B3E" +
+ "008E3BDB2E11F9193388F1F901CCC857BF49CFC065FB38B9069CAAE6D5AFC3592F" +
+ "004555122AAC0075F42E0A8BBD2C0665C789120DF19D77B4E3EE4712F598040415",
+ /* 7 p.76 ZB */
+ "0088" +
+ "42494C4C343536405941484F4F2E434F4D" +
+ "000000000000000000000000000000000000000000000000000000000000000000" +
+ "00E78BCD09746C202378A7E72B12BCE00266B9627ECB0B5A25367AD1AD4CC6242B" +
+ "00CDB9CA7F1E6B0441F658343F4B10297C0EF9B6491082400A62E7A7485735FADD" +
+ "013DE74DA65951C4D76DC89220D5F7777A611B1C38BAE260B175951DC8060C2B3E" +
+ "0034297DD83AB14D5B393B6712F32B2F2E938D4690B095424B89DA880C52D4A7D9" +
+ "0199BBF11AC95A0EA34BBD00CA50B93EC24ACB68335D20BA5DCFE3B33BDBD2B62D",
+ /* 8 TopsecCA cert ZA */
+ "0080" +
+ "31323334353637383132333435363738" +
+ "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC" +
+ "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93" +
+ "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7" +
+ "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0" +
+ "D69C2F1EEC3BFB6B95B30C28085C77B125D77A9C39525D8190768F37D6B205B5" +
+ "89DCD316BBE7D89A9DC21917F17799E698531F5E6E3E10BD31370B259C3F81C3",
+ /* 9 */
+ "4D38D2958CA7FD2CFAE3AF04486959CF92C8EF48E8B83A05C112E739D5F181D0" +
+ "3082020CA003020102020900" +
+ "AF28725D98D33143300C06082A811CCF" +
+ "550183750500307D310B300906035504" +
+ "060C02636E310B300906035504080C02" +
+ "626A310B300906035504070C02626A31" +
+ "0F300D060355040A0C06746F70736563" +
+ "310F300D060355040B0C06746F707365" +
+ "633111300F06035504030C08546F7073" +
+ "65634341311F301D06092A864886F70D" +
+ "0109010C10626A40746F707365632E63" +
+ "6F6D2E636E301E170D31323036323430" +
+ "37353433395A170D3332303632303037" +
+ "353433395A307D310B30090603550406" +
+ "0C02636E310B300906035504080C0262" +
+ "6A310B300906035504070C02626A310F" +
+ "300D060355040A0C06746F7073656331" +
+ "0F300D060355040B0C06746F70736563" +
+ "3111300F06035504030C08546F707365" +
+ "634341311F301D06092A864886F70D01" +
+ "09010C10626A40746F707365632E636F" +
+ "6D2E636E3059301306072A8648CE3D02" +
+ "0106082A811CCF5501822D03420004D6" +
+ "9C2F1EEC3BFB6B95B30C28085C77B125" +
+ "D77A9C39525D8190768F37D6B205B589" +
+ "DCD316BBE7D89A9DC21917F17799E698" +
+ "531F5E6E3E10BD31370B259C3F81C3A3" +
+ "733071300F0603551D130101FF040530" +
+ "030101FF301D0603551D0E041604148E" +
+ "5D90347858BAAAD870D8BDFBA6A85E7B" +
+ "563B64301F0603551D23041830168014" +
+ "8E5D90347858BAAAD870D8BDFBA6A85E" +
+ "7B563B64300B0603551D0F0404030201" +
+ "06301106096086480186F84201010404" +
+ "03020057",
+ };
+
+ private static string[] digests = {
// Standard test vectors
"66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0",
"debe9ff92275b8a138604889c18e5a4d6fdb70e5387e5765293dcba39c0c5732",
@@ -34,7 +134,16 @@ namespace Org.BouncyCastle.Crypto.Tests
"1ab21d8355cfa17f8e61194831e81a8f22bec8c728fefb747ed035eb5082aa2b",
"623476ac18f65a2909e43c7fec61b49c7e764a91a18ccb82f1917a29c86c5e88",
"b80fe97a4da24afc277564f66a359ef440462ad28dcc6d63adb24d5c20a61595",
- };
+ // Additional vectors for GMSSL
+ "F4A38489E32B45B6F876E3AC2168CA392362DC8F23459C1D1146FC3DBFB7BC9A",
+ "26352AF82EC19F207BBC6F9474E11E90CE0F7DDACE03B27F801817E897A81FD5",
+ "E4D1D0C3CA4C7F11BC8FF8CB3F4C02A78F108FA098E51A668487240F75E20F31",
+ "6B4B6D0E276691BD4A11BF72F4FB501AE309FDACB72FA6CC336E6656119ABD67",
+ "329c2f6030cc7e0ca3af6c97b76243ca250338ad3d3dc3a8b322d1cfdf98c2b7", // original appears wrong -> "ECF0080215977B2E5D6D61B98A99442F03E8803DC39E349F8DCA5621A9ACDF2B",
+ "557BAD30E183559AEEC3B2256E1C7C11F870D22B165D015ACF9465B09B87B527",
+ "4D38D2958CA7FD2CFAE3AF04486959CF92C8EF48E8B83A05C112E739D5F181D0",
+ "C3B02E500A8B60B77DEDCF6F4C11BEF8D56E5CDE708C72065654FD7B2167915A",
+ };
private static string sixtyFourKdigest = "97049bdc8f0736bc7300eafa9980aeb9cf00f24f7ec3a8f1f8884954d7655c1d";
private static string million_a_digest = "c8aaf89429554029e231941a2acc0ad61ff2a5acd8fadd25847a3a732b3b02c3";
@@ -48,11 +157,35 @@ namespace Org.BouncyCastle.Crypto.Tests
{
base.PerformTest();
- sixtyFourKTest(sixtyFourKdigest);
+ SM3Digest dig = new SM3Digest();
+ byte[] resBuf = new byte[dig.GetDigestSize()];
+
+ VectorTest(dig, 10, resBuf, Hex.Decode(hexMessages[0]), Hex.Decode(digests[messages.Length]));
+ VectorTest(dig, 11, resBuf, Hex.Decode(hexMessages[1]), Hex.Decode(digests[messages.Length + 1]));
+ VectorTest(dig, 12, resBuf, Hex.Decode(hexMessages[2]), Hex.Decode(digests[messages.Length + 2]));
+ VectorTest(dig, 13, resBuf, Hex.Decode(hexMessages[3]), Hex.Decode(digests[messages.Length + 3]));
+ VectorTest(dig, 14, resBuf, Hex.Decode(hexMessages[4]), Hex.Decode(digests[messages.Length + 4]));
+ VectorTest(dig, 15, resBuf, Hex.Decode(hexMessages[5]), Hex.Decode(digests[messages.Length + 5]));
+ VectorTest(dig, 16, resBuf, Hex.Decode(hexMessages[6]), Hex.Decode(digests[messages.Length + 6]));
+ VectorTest(dig, 17, resBuf, Hex.Decode(hexMessages[7]), Hex.Decode(digests[messages.Length + 7]));
+
+ sixtyFourKTest(sixtyFourKdigest);
millionATest(million_a_digest);
}
- protected override IDigest CloneDigest(IDigest digest)
+ protected virtual void VectorTest(IDigest digest, int count,
+ byte[] resBuf, byte[] input, byte[] expected)
+ {
+ digest.BlockUpdate(input, 0, input.Length);
+ digest.DoFinal(resBuf, 0);
+
+ if (!AreEqual(resBuf, expected))
+ {
+ Fail("Vector " + count + " failed got " + Hex.ToHexString(resBuf));
+ }
+ }
+
+ protected override IDigest CloneDigest(IDigest digest)
{
return new SM3Digest((SM3Digest)digest);
}
diff --git a/crypto/test/src/openpgp/test/PGPSignatureTest.cs b/crypto/test/src/openpgp/test/PGPSignatureTest.cs
index 6aca68134..23220cad3 100644
--- a/crypto/test/src/openpgp/test/PGPSignatureTest.cs
+++ b/crypto/test/src/openpgp/test/PGPSignatureTest.cs
@@ -326,8 +326,49 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
+ "6YD9JpfYZHEFmpYoS+qQ3tLfPCG3gaS/djBZWWkNt5z7e6sbRko49XEj3EUh"
+ "33HgjrOlL8uJNbhlZ5NeILcxHqGTHji+5wMEDBjfNT/C6m0=");
+ private void DoTestRemoveSignature()
+ {
+ byte[] testPubKeyRing =
+ Base64.Decode(
+ "mQGiBEAR8jYRBADNifuSopd20JOQ5x30ljIaY0M6927+vo09NeNxS3KqItba"
+ + "nz9o5e2aqdT0W1xgdHYZmdElOHTTsugZxdXTEhghyxoo3KhVcNnTABQyrrvX"
+ + "qouvmP2fEDEw0Vpyk+90BpyY9YlgeX/dEA8OfooRLCJde/iDTl7r9FT+mts8"
+ + "g3azjwCgx+pOLD9LPBF5E4FhUOdXISJ0f4EEAKXSOi9nZzajpdhe8W2ZL9gc"
+ + "BpzZi6AcrRZBHOEMqd69gtUxA4eD8xycUQ42yH89imEcwLz8XdJ98uHUxGJi"
+ + "qp6hq4oakmw8GQfiL7yQIFgaM0dOAI9Afe3m84cEYZsoAFYpB4/s9pVMpPRH"
+ + "NsVspU0qd3NHnSZ0QXs8L8DXGO1uBACjDUj+8GsfDCIP2QF3JC+nPUNa0Y5t"
+ + "wKPKl+T8hX/0FBD7fnNeC6c9j5Ir/Fp/QtdaDAOoBKiyNLh1JaB1NY6US5zc"
+ + "qFks2seZPjXEiE6OIDXYra494mjNKGUobA4hqT2peKWXt/uBcuL1mjKOy8Qf"
+ + "JxgEd0MOcGJO+1PFFZWGzLQ3RXJpYyBILiBFY2hpZG5hICh0ZXN0IGtleSBv"
+ + "bmx5KSA8ZXJpY0Bib3VuY3ljYXN0bGUub3JnPohZBBMRAgAZBQJAEfI2BAsH"
+ + "AwIDFQIDAxYCAQIeAQIXgAAKCRAOtk6iUOgnkDdnAKC/CfLWikSBdbngY6OK"
+ + "5UN3+o7q1ACcDRqjT3yjBU3WmRUNlxBg3tSuljmwAgAAuQENBEAR8jgQBAC2"
+ + "kr57iuOaV7Ga1xcU14MNbKcA0PVembRCjcVjei/3yVfT/fuCVtGHOmYLEBqH"
+ + "bn5aaJ0P/6vMbLCHKuN61NZlts+LEctfwoya43RtcubqMc7eKw4k0JnnoYgB"
+ + "ocLXOtloCb7jfubOsnfORvrUkK0+Ne6anRhFBYfaBmGU75cQgwADBQP/XxR2"
+ + "qGHiwn+0YiMioRDRiIAxp6UiC/JQIri2AKSqAi0zeAMdrRsBN7kyzYVVpWwN"
+ + "5u13gPdQ2HnJ7d4wLWAuizUdKIQxBG8VoCxkbipnwh2RR4xCXFDhJrJFQUm+"
+ + "4nKx9JvAmZTBIlI5Wsi5qxst/9p5MgP3flXsNi1tRbTmRhqIRgQYEQIABgUC"
+ + "QBHyOAAKCRAOtk6iUOgnkBStAJoCZBVM61B1LG2xip294MZecMtCwQCbBbsk"
+ + "JVCXP0/Szm05GB+WN+MOCT2wAgAA");
+
+ PgpObjectFactory pgpFact = new PgpObjectFactory(testPubKeyRing);
+
+ PgpPublicKeyRing pgpPub = (PgpPublicKeyRing)pgpFact.NextPgpObject();
+
+ foreach (PgpSignature sig in pgpPub.GetPublicKey().GetSignatures())
+ {
+ if (sig.SignatureType == PgpSignature.PositiveCertification)
+ {
+ PgpPublicKey.RemoveCertification(pgpPub.GetPublicKey(), sig);
+ }
+ }
+ }
+
public override void PerformTest()
{
+ DoTestRemoveSignature();
+
//
// RSA tests
//
diff --git a/crypto/test/src/test/CertTest.cs b/crypto/test/src/test/CertTest.cs
index 8632bac68..9a4965297 100644
--- a/crypto/test/src/test/CertTest.cs
+++ b/crypto/test/src/test/CertTest.cs
@@ -19,6 +19,7 @@ using Org.BouncyCastle.Security;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Utilities.Collections;
using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.IO;
using Org.BouncyCastle.Utilities.Test;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.X509.Extension;
@@ -2426,6 +2427,19 @@ namespace Org.BouncyCastle.Tests
return new AsymmetricCipherKeyPair(pubKey, privKey);
}
+ private void rfc4491Test()
+ {
+ X509CertificateParser certFact = new X509CertificateParser();
+
+ X509Certificate x509 = certFact.ReadCertificate(new MemoryStream(gostRFC4491_94, false));
+
+ x509.Verify(x509.GetPublicKey());
+
+ x509 = (X509Certificate)certFact.ReadCertificate(new MemoryStream(gostRFC4491_2001, false));
+
+ x509.Verify(x509.GetPublicKey());
+ }
+
private void doTestNullDerNullCert()
{
AsymmetricCipherKeyPair keyPair = GenerateLongFixedKeys();
@@ -2469,6 +2483,71 @@ namespace Org.BouncyCastle.Tests
}
}
+ private void pemFileTest()
+ {
+ X509CertificateParser fact = new X509CertificateParser();
+
+ ICollection certs1 = fact.ReadCertificates(GetTestDataAsStream("cert_chain.data"));
+ IsTrue("certs wrong <cr><nl>", 2 == certs1.Count);
+
+ MemoryStream input = new MemoryStream(Streams.ReadAll(GetTestDataAsStream("cert_chain.data")), false);
+
+ ISet certs2 = new HashSet();
+ while (input.Position < input.Length)
+ {
+ X509Certificate c = fact.ReadCertificate(input);
+
+ // this isn't strictly correct with the way it's defined in the Java JavaDoc - need it for backward
+ // compatibility.
+ if (c != null)
+ {
+ certs2.Add(c);
+ }
+ }
+ IsTrue("certs size <cr><nl>", certs1.Count == certs2.Count);
+
+ certs2.RemoveAll(certs1);
+ IsTrue("collection not empty", certs2.Count == 0);
+ }
+
+ private void invalidCrls()
+ {
+ X509CrlParser crlParser = new X509CrlParser();
+
+ ICollection crls = crlParser.ReadCrls(GetTestDataAsStream("cert_chain.data"));
+ IsTrue("multi crl", crls.Count == 0);
+
+ X509Crl crl = crlParser.ReadCrl(GetTestDataAsStream("cert_chain.data"));
+ IsTrue("single crl", crl == null);
+ }
+
+ private void pemFileTestWithNl()
+ {
+ X509CertificateParser fact = new X509CertificateParser();
+
+ ICollection certs1 = fact.ReadCertificates(GetTestDataAsStream("cert_chain_nl.data"));
+ IsTrue("certs wrong <nl>", 2 == certs1.Count);
+
+ MemoryStream input = new MemoryStream(Streams.ReadAll(GetTestDataAsStream("cert_chain_nl.data")), false);
+
+ ISet certs2 = new HashSet();
+ while (input.Position < input.Length)
+ {
+ X509Certificate c = fact.ReadCertificate(input);
+
+ // this isn't strictly correct with the way it's defined in the Java JavaDoc - need it for backward
+ // compatibility.
+ if (c != null)
+ {
+ certs2.Add(c);
+ }
+ }
+ IsTrue("certs size <nl>", certs1.Count == certs2.Count);
+
+ certs2.RemoveAll(certs1);
+ IsTrue("collection not empty", certs2.Count == 0);
+ }
+
public override void PerformTest()
{
checkCertificate(1, cert1);
@@ -2518,7 +2597,12 @@ namespace Org.BouncyCastle.Tests
checkCrlCreation3();
pemTest();
+ pemFileTest();
+ pemFileTestWithNl();
pkcs7Test();
+ rfc4491Test();
+
+ invalidCrls();
doTestForgedSignature();
diff --git a/crypto/test/src/test/NamedCurveTest.cs b/crypto/test/src/test/NamedCurveTest.cs
index 96b246981..5b29a4152 100644
--- a/crypto/test/src/test/NamedCurveTest.cs
+++ b/crypto/test/src/test/NamedCurveTest.cs
@@ -240,18 +240,39 @@ namespace Org.BouncyCastle.Tests
// }
}
- public void doTestECGost(
- string name)
+ public void doTestECGost(string name)
{
-// ECGenParameterSpec ecSpec = new ECGenParameterSpec(name);
- ECDomainParameters ecSpec = GetCurveParameters(name);
+ ISigner sgr;
+ string keyAlgorithm;
- IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("ECGOST3410");
+ if (name.IndexOf("Tc26-Gost-3410") == 0)
+ {
+ // TODO Implement ECGOST3410-2012 in SignerUtilies/GeneratorUtilities etc.
+ // Current test cases don't work for GOST34.10 2012
+ return;
+
+ keyAlgorithm = "ECGOST3410-2012";
+ if (name.IndexOf("256") > 0)
+ {
+ sgr = SignerUtilities.GetSigner("ECGOST3410-2012-256");
+ }
+ else
+ {
+ sgr = SignerUtilities.GetSigner("ECGOST3410-2012-512");
+ }
+ }
+ else
+ {
+ keyAlgorithm = "ECGOST3410";
-// g.initialize(ecSpec, new SecureRandom());
+ sgr = SignerUtilities.GetSigner("ECGOST3410");
+ }
+
+ ECDomainParameters ecSpec = GetCurveParameters(name);
+
+ IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator(keyAlgorithm);
g.Init(new ECKeyGenerationParameters(ecSpec, new SecureRandom()));
- ISigner sgr = SignerUtilities.GetSigner("ECGOST3410");
AsymmetricCipherKeyPair pair = g.GenerateKeyPair();
AsymmetricKeyParameter sKey = pair.Private;
AsymmetricKeyParameter vKey = pair.Public;
@@ -280,7 +301,7 @@ namespace Org.BouncyCastle.Tests
//// byte[] pubEnc = vKey.getEncoded();
// byte[] pubEnc = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(vKey).GetDerEncoded();
//
-//// KeyFactory keyFac = KeyFactory.getInstance("ECGOST3410");
+//// KeyFactory keyFac = KeyFactory.getInstance(keyAlgorithm);
//// X509EncodedKeySpec pubX509 = new X509EncodedKeySpec(pubEnc);
//// ECPublicKey pubKey = (ECPublicKey)keyFac.generatePublic(pubX509);
// ECPublicKeyParameters pubKey = (ECPublicKeyParameters) PublicKeyFactory.CreateKey(pubEnc);
diff --git a/crypto/test/src/util/test/FixedSecureRandom.cs b/crypto/test/src/util/test/FixedSecureRandom.cs
index d8598ac24..1368aa231 100644
--- a/crypto/test/src/util/test/FixedSecureRandom.cs
+++ b/crypto/test/src/util/test/FixedSecureRandom.cs
@@ -2,16 +2,90 @@ using System;
using System.IO;
using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+
+using M = Org.BouncyCastle.Math;
namespace Org.BouncyCastle.Utilities.Test
{
public class FixedSecureRandom
: SecureRandom
{
+ private static readonly M.BigInteger REGULAR = new M.BigInteger("01020304ffffffff0506070811111111", 16);
+ private static readonly M.BigInteger ANDROID = new M.BigInteger("1111111105060708ffffffff01020304", 16);
+ private static readonly M.BigInteger CLASSPATH = new M.BigInteger("3020104ffffffff05060708111111", 16);
+
+ private static readonly bool isAndroidStyle;
+ private static readonly bool isClasspathStyle;
+ private static readonly bool isRegularStyle;
+
+ static FixedSecureRandom()
+ {
+ M.BigInteger check1 = new M.BigInteger(128, new RandomChecker());
+ M.BigInteger check2 = new M.BigInteger(120, new RandomChecker());
+
+ isAndroidStyle = check1.Equals(ANDROID);
+ isRegularStyle = check1.Equals(REGULAR);
+ isClasspathStyle = check2.Equals(CLASSPATH);
+ }
+
private byte[] _data;
private int _index;
- protected FixedSecureRandom(
+ /**
+ * Base class for sources of fixed "Randomness"
+ */
+ public class Source
+ {
+ internal byte[] data;
+
+ internal Source(byte[] data)
+ {
+ this.data = data;
+ }
+ }
+
+ /**
+ * Data Source - in this case we just expect requests for byte arrays.
+ */
+ public class Data
+ : Source
+ {
+ public Data(byte[] data)
+ : base(data)
+ {
+ }
+ }
+
+ /**
+ * BigInteger Source - in this case we expect requests for data that will be used
+ * for BigIntegers. The FixedSecureRandom will attempt to compensate for platform differences here.
+ */
+ public class BigInteger
+ : Source
+ {
+ public BigInteger(byte[] data)
+ : base(data)
+ {
+ }
+
+ public BigInteger(int bitLength, byte[] data)
+ : base(ExpandToBitLength(bitLength, data))
+ {
+ }
+
+ public BigInteger(string hexData)
+ : this(Hex.Decode(hexData))
+ {
+ }
+
+ public BigInteger(int bitLength, string hexData)
+ : base(ExpandToBitLength(bitLength, Hex.Decode(hexData)))
+ {
+ }
+ }
+
+ protected FixedSecureRandom(
byte[] data)
{
_data = data;
@@ -38,6 +112,103 @@ namespace Org.BouncyCastle.Utilities.Test
return new FixedSecureRandom(bOut.ToArray());
}
+ public FixedSecureRandom(
+ Source[] sources)
+ {
+ MemoryStream bOut = new MemoryStream();
+
+ if (isRegularStyle)
+ {
+ if (isClasspathStyle)
+ {
+ for (int i = 0; i != sources.Length; i++)
+ {
+ try
+ {
+ if (sources[i] is BigInteger)
+ {
+ byte[] data = sources[i].data;
+ int len = data.Length - (data.Length % 4);
+ for (int w = data.Length - len - 1; w >= 0; w--)
+ {
+ bOut.WriteByte(data[w]);
+ }
+ for (int w = data.Length - len; w < data.Length; w += 4)
+ {
+ bOut.Write(data, w, 4);
+ }
+ }
+ else
+ {
+ bOut.Write(sources[i].data, 0, sources[i].data.Length);
+ }
+ }
+ catch (IOException e)
+ {
+ throw new ArgumentException("can't save value source.");
+ }
+ }
+ }
+ else
+ {
+ for (int i = 0; i != sources.Length; i++)
+ {
+ try
+ {
+ bOut.Write(sources[i].data, 0, sources[i].data.Length);
+ }
+ catch (IOException e)
+ {
+ throw new ArgumentException("can't save value source.");
+ }
+ }
+ }
+ }
+ else if (isAndroidStyle)
+ {
+ for (int i = 0; i != sources.Length; i++)
+ {
+ try
+ {
+ if (sources[i] is BigInteger)
+ {
+ byte[] data = sources[i].data;
+ int len = data.Length - (data.Length % 4);
+ for (int w = 0; w < len; w += 4)
+ {
+ bOut.Write(data, data.Length - (w + 4), 4);
+ }
+ if (data.Length - len != 0)
+ {
+ for (int w = 0; w != 4 - (data.Length - len); w++)
+ {
+ bOut.WriteByte(0);
+ }
+ }
+ for (int w = 0; w != data.Length - len; w++)
+ {
+ bOut.WriteByte(data[len + w]);
+ }
+ }
+ else
+ {
+ bOut.Write(sources[i].data, 0, sources[i].data.Length);
+ }
+ }
+ catch (IOException e)
+ {
+ throw new ArgumentException("can't save value source.");
+ }
+ }
+ }
+ else
+ {
+ throw new InvalidOperationException("Unrecognized BigInteger implementation");
+ }
+
+ _data = bOut.ToArray();
+ }
+
public override byte[] GenerateSeed(int numBytes)
{
return SecureRandom.GetNextBytes(this, numBytes);
@@ -65,5 +236,68 @@ namespace Org.BouncyCastle.Utilities.Test
{
get { return _index == _data.Length; }
}
+
+ private class RandomChecker
+ : SecureRandom
+ {
+ byte[] data = Hex.Decode("01020304ffffffff0506070811111111");
+ int index = 0;
+
+ public override void NextBytes(byte[] bytes)
+ {
+ Array.Copy(data, index, bytes, 0, bytes.Length);
+
+ index += bytes.Length;
+ }
+ }
+
+ private static byte[] ExpandToBitLength(int bitLength, byte[] v)
+ {
+ if ((bitLength + 7) / 8 > v.Length)
+ {
+ byte[] tmp = new byte[(bitLength + 7) / 8];
+
+ Array.Copy(v, 0, tmp, tmp.Length - v.Length, v.Length);
+ if (isAndroidStyle)
+ {
+ if (bitLength % 8 != 0)
+ {
+ uint i = BE_To_UInt32(tmp, 0);
+ UInt32_To_BE(i << (8 - (bitLength % 8)), tmp, 0);
+ }
+ }
+
+ return tmp;
+ }
+ else
+ {
+ if (isAndroidStyle && bitLength < (v.Length * 8))
+ {
+ if (bitLength % 8 != 0)
+ {
+ uint i = BE_To_UInt32(v, 0);
+ UInt32_To_BE(i << (8 - (bitLength % 8)), v, 0);
+ }
+ }
+ }
+
+ return v;
+ }
+
+ internal static uint BE_To_UInt32(byte[] bs, int off)
+ {
+ return (uint)bs[off] << 24
+ | (uint)bs[off + 1] << 16
+ | (uint)bs[off + 2] << 8
+ | (uint)bs[off + 3];
+ }
+
+ internal static void UInt32_To_BE(uint n, byte[] bs, int off)
+ {
+ bs[off] = (byte)(n >> 24);
+ bs[off + 1] = (byte)(n >> 16);
+ bs[off + 2] = (byte)(n >> 8);
+ bs[off + 3] = (byte)(n);
+ }
}
}
diff --git a/crypto/test/src/util/test/SimpleTest.cs b/crypto/test/src/util/test/SimpleTest.cs
index 1639431cc..45b8a6a06 100644
--- a/crypto/test/src/util/test/SimpleTest.cs
+++ b/crypto/test/src/util/test/SimpleTest.cs
@@ -27,6 +27,12 @@ namespace Org.BouncyCastle.Utilities.Test
throw new TestFailedException(SimpleTestResult.Failed(this, message));
}
+ internal void IsTrue(bool value)
+ {
+ if (!value)
+ throw new TestFailedException(SimpleTestResult.Failed(this, "no message"));
+ }
+
internal void IsTrue(string message, bool value)
{
if (!value)
diff --git a/crypto/test/src/util/test/TestRandomBigInteger.cs b/crypto/test/src/util/test/TestRandomBigInteger.cs
new file mode 100644
index 000000000..ef38293b9
--- /dev/null
+++ b/crypto/test/src/util/test/TestRandomBigInteger.cs
@@ -0,0 +1,55 @@
+using System;
+
+using M = Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Utilities.Test
+{
+ /**
+ * A fixed secure random designed to return data for someone needing to create a single BigInteger.
+ */
+ public class TestRandomBigInteger
+ : FixedSecureRandom
+ {
+ /**
+ * Constructor from a base 10 represention of a BigInteger.
+ *
+ * @param encoding a base 10 represention of a BigInteger.
+ */
+ public TestRandomBigInteger(string encoding)
+ : this(encoding, 10)
+ {
+ }
+
+ /**
+ * Constructor from a base radix represention of a BigInteger.
+ *
+ * @param encoding a String BigInteger of base radix.
+ * @param radix the radix to use.
+ */
+ public TestRandomBigInteger(string encoding, int radix)
+ : base(new FixedSecureRandom.Source[] { new FixedSecureRandom.BigInteger(BigIntegers.AsUnsignedByteArray(new M.BigInteger(encoding, radix))) })
+ {
+ }
+
+ /**
+ * Constructor based on a byte array.
+ *
+ * @param encoding a 2's complement representation of the BigInteger.
+ */
+ public TestRandomBigInteger(byte[] encoding)
+ : base(new FixedSecureRandom.Source[] { new FixedSecureRandom.BigInteger(encoding) })
+ {
+ }
+
+ /**
+ * Constructor which ensures encoding will produce a BigInteger from a request from the passed in bitLength.
+ *
+ * @param bitLength bit length for the BigInteger data request.
+ * @param encoding bytes making up the encoding.
+ */
+ public TestRandomBigInteger(int bitLength, byte[] encoding)
+ : base(new FixedSecureRandom.Source[] { new FixedSecureRandom.BigInteger(bitLength, encoding) })
+ {
+ }
+ }
+}
diff --git a/crypto/test/src/util/test/UncloseableStream.cs b/crypto/test/src/util/test/UncloseableStream.cs
index 2a3b4229b..0a7a16e66 100644
--- a/crypto/test/src/util/test/UncloseableStream.cs
+++ b/crypto/test/src/util/test/UncloseableStream.cs
@@ -5,6 +5,11 @@ using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Utilities.Test
{
+ /// <summary>
+ /// This is a testing utility class to check the property that a <c>Stream</c> is never
+ /// closed in some particular context - typically when wrapped by another <c>Stream</c> that
+ /// should not be forwarding its <c>Stream.Close()</c> calls. Not needed in production code.
+ /// </summary>
public class UncloseableStream
: FilterStream
{
|