summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crypto/crypto.csproj100
-rw-r--r--crypto/src/asn1/cryptopro/ECGOST3410NamedCurves.cs89
-rw-r--r--crypto/src/asn1/esf/SignerLocation.cs106
-rw-r--r--crypto/src/asn1/rosstandart/RosstandartObjectIdentifiers.cs47
-rw-r--r--crypto/src/asn1/x500/DirectoryString.cs9
-rw-r--r--crypto/src/asn1/x9/ECNamedCurveTable.cs24
-rw-r--r--crypto/src/crypto/agreement/SM2KeyExchange.cs272
-rw-r--r--crypto/src/crypto/agreement/kdf/ConcatenationKdfGenerator.cs100
-rw-r--r--crypto/src/crypto/digests/DSTU7564Digest.cs785
-rw-r--r--crypto/src/crypto/engines/Dstu7624Engine.cs97
-rw-r--r--crypto/src/crypto/engines/SM2Engine.cs238
-rw-r--r--crypto/src/crypto/generators/HKDFBytesGenerator.cs1
-rw-r--r--crypto/src/crypto/parameters/ParametersWithID.cs36
-rw-r--r--crypto/src/crypto/parameters/ParametersWithIV.cs41
-rw-r--r--crypto/src/crypto/parameters/SM2KeyExchangePrivateParameters.cs64
-rw-r--r--crypto/src/crypto/parameters/SM2KeyExchangePublicParameters.cs40
-rw-r--r--crypto/src/crypto/prng/CryptoApiEntropySourceProvider.cs2
-rw-r--r--crypto/src/crypto/prng/CryptoApiRandomGenerator.cs4
-rw-r--r--crypto/src/crypto/signers/SM2Signer.cs258
-rw-r--r--crypto/src/crypto/tls/CertificateStatus.cs2
-rw-r--r--crypto/src/crypto/tls/CertificateStatusRequest.cs2
-rw-r--r--crypto/src/crypto/tls/ServerName.cs2
-rw-r--r--crypto/src/math/ec/multiplier/FixedPointCombMultiplier.cs2
-rw-r--r--crypto/src/math/ec/multiplier/FixedPointPreCompInfo.cs10
-rw-r--r--crypto/src/math/ec/multiplier/FixedPointUtilities.cs10
-rw-r--r--crypto/src/util/encoders/Base64Encoder.cs3
-rw-r--r--crypto/test/data/ThawteSGCCA.cerbin0 -> 807 bytes
-rw-r--r--crypto/test/data/ThawteSGCCA.crlbin0 -> 55139 bytes
-rw-r--r--crypto/test/data/cert_chain.data60
-rw-r--r--crypto/test/data/cert_chain_nl.data59
-rw-r--r--crypto/test/data/cms/sigs/SignedMSPkcs7.sigbin0 -> 4927 bytes
-rw-r--r--crypto/test/data/cms/sigs/rawsha256nonull.p7mbin0 -> 1415 bytes
-rw-r--r--crypto/test/data/qvRooCa3.crt38
-rw-r--r--crypto/test/data/suvaEE.crt32
-rw-r--r--crypto/test/data/suvaEmail1.crt39
-rw-r--r--crypto/test/data/suvaRoot1.crt46
-rw-r--r--crypto/test/src/asn1/test/SignerLocationUnitTest.cs24
-rw-r--r--crypto/test/src/cms/test/SignedDataTest.cs18
-rw-r--r--crypto/test/src/crypto/test/DSTU7564Test.cs487
-rw-r--r--crypto/test/src/crypto/test/RegressionTest.cs3
-rw-r--r--crypto/test/src/crypto/test/SM2EngineTest.cs167
-rw-r--r--crypto/test/src/crypto/test/SM2KeyExchangeTest.cs229
-rw-r--r--crypto/test/src/crypto/test/SM2SignerTest.cs193
-rw-r--r--crypto/test/src/crypto/test/SM3DigestTest.cs145
-rw-r--r--crypto/test/src/openpgp/test/PGPSignatureTest.cs41
-rw-r--r--crypto/test/src/test/CertTest.cs84
-rw-r--r--crypto/test/src/test/NamedCurveTest.cs37
-rw-r--r--crypto/test/src/util/test/FixedSecureRandom.cs236
-rw-r--r--crypto/test/src/util/test/SimpleTest.cs6
-rw-r--r--crypto/test/src/util/test/TestRandomBigInteger.cs55
-rw-r--r--crypto/test/src/util/test/UncloseableStream.cs5
51 files changed, 3512 insertions, 836 deletions
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 {