From 3329b24132fc59aca54c6ed8407b4a75bc5a7fce Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Thu, 1 Jun 2017 17:03:32 +0700 Subject: Tighten up no_certificate alert handling --- crypto/src/crypto/tls/TlsServerProtocol.cs | 31 ++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/tls/TlsServerProtocol.cs b/crypto/src/crypto/tls/TlsServerProtocol.cs index 5f3ce18e2..298c9f42d 100644 --- a/crypto/src/crypto/tls/TlsServerProtocol.cs +++ b/crypto/src/crypto/tls/TlsServerProtocol.cs @@ -388,26 +388,37 @@ namespace Org.BouncyCastle.Crypto.Tls protected override void HandleWarningMessage(byte description) { + base.HandleWarningMessage(description); + switch (description) { case AlertDescription.no_certificate: { /* - * SSL 3.0 If the server has sent a certificate request Message, the client must Send + * SSL 3.0 If the server has sent a certificate request Message, the client must send * either the certificate message or a no_certificate alert. */ - if (TlsUtilities.IsSsl(Context) && mCertificateRequest != null) + if (TlsUtilities.IsSsl(Context) && this.mCertificateRequest != null) { - NotifyClientCertificate(Certificate.EmptyChain); + switch (this.mConnectionState) + { + case CS_SERVER_HELLO_DONE: + case CS_CLIENT_SUPPLEMENTAL_DATA: + { + if (mConnectionState < CS_CLIENT_SUPPLEMENTAL_DATA) + { + mTlsServer.ProcessClientSupplementalData(null); + } + + NotifyClientCertificate(Certificate.EmptyChain); + this.mConnectionState = CS_CLIENT_CERTIFICATE; + return; + } + } } - break; - } - default: - { - base.HandleWarningMessage(description); - break; - } + throw new TlsFatalAlert(AlertDescription.unexpected_message); } + } } protected virtual void NotifyClientCertificate(Certificate clientCertificate) -- cgit 1.4.1 From 86f0665ac96629cf1cbb6967383b391fb051a895 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Thu, 1 Jun 2017 17:06:41 +0700 Subject: Improve error handling/messages --- crypto/src/crypto/tls/TlsProtocol.cs | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/tls/TlsProtocol.cs b/crypto/src/crypto/tls/TlsProtocol.cs index 490580fad..5a1c08616 100644 --- a/crypto/src/crypto/tls/TlsProtocol.cs +++ b/crypto/src/crypto/tls/TlsProtocol.cs @@ -10,8 +10,6 @@ namespace Org.BouncyCastle.Crypto.Tls { public abstract class TlsProtocol { - private static readonly string TLS_ERROR_MESSAGE = "Internal TLS error, this could be an attack"; - /* * Our Connection states */ @@ -386,8 +384,12 @@ namespace Org.BouncyCastle.Crypto.Tls this.mClosed = true; mRecordStream.SafeClose(); + if (!mAppDataReady) + { + CleanupHandshake(); + } - throw new IOException(TLS_ERROR_MESSAGE); + throw new IOException("Fatal alert received from TLS peer: " + AlertDescription.GetText(description)); } else { @@ -464,22 +466,14 @@ namespace Org.BouncyCastle.Crypto.Tls while (mApplicationDataQueue.Available == 0) { - /* - * We need to read some data. - */ if (this.mClosed) { if (this.mFailedWithError) - { - /* - * Something went terribly wrong, we should throw an IOException - */ - throw new IOException(TLS_ERROR_MESSAGE); - } + throw new IOException("Cannot read application data on failed TLS connection"); + + if (!mAppDataReady) + throw new InvalidOperationException("Cannot read application data until initial handshake completed."); - /* - * Connection has been closed, there is no more data to read. - */ return 0; } @@ -577,12 +571,7 @@ namespace Org.BouncyCastle.Crypto.Tls protected internal virtual void WriteData(byte[] buf, int offset, int len) { if (this.mClosed) - { - if (this.mFailedWithError) - throw new IOException(TLS_ERROR_MESSAGE); - - throw new IOException("Sorry, connection has been closed, you cannot write more data"); - } + throw new IOException("Cannot write application data on closed/failed TLS connection"); while (len > 0) { @@ -884,7 +873,7 @@ namespace Org.BouncyCastle.Crypto.Tls } } - throw new IOException(TLS_ERROR_MESSAGE); + throw new IOException("TLS connection failed"); } protected virtual void InvalidateSession() -- cgit 1.4.1 From e0b74ac5076f2b2ff2430110530014bd114584e7 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sat, 3 Jun 2017 17:54:33 +0700 Subject: Fix reductions for custom secp128r1 field --- crypto/src/math/ec/custom/sec/SecP128R1Field.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'crypto') diff --git a/crypto/src/math/ec/custom/sec/SecP128R1Field.cs b/crypto/src/math/ec/custom/sec/SecP128R1Field.cs index ff6fb6b65..d1ac009b3 100644 --- a/crypto/src/math/ec/custom/sec/SecP128R1Field.cs +++ b/crypto/src/math/ec/custom/sec/SecP128R1Field.cs @@ -19,7 +19,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public static void Add(uint[] x, uint[] y, uint[] z) { uint c = Nat128.Add(x, y, z); - if (c != 0 || (z[3] == P3 && Nat128.Gte(z, P))) + if (c != 0 || (z[3] >= P3 && Nat128.Gte(z, P))) { AddPInvTo(z); } @@ -28,7 +28,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public static void AddExt(uint[] xx, uint[] yy, uint[] zz) { uint c = Nat256.Add(xx, yy, zz); - if (c != 0 || (zz[7] == PExt7 && Nat256.Gte(zz, PExt))) + if (c != 0 || (zz[7] >= PExt7 && Nat256.Gte(zz, PExt))) { Nat.AddTo(PExtInv.Length, PExtInv, zz); } @@ -37,7 +37,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public static void AddOne(uint[] x, uint[] z) { uint c = Nat.Inc(4, x, z); - if (c != 0 || (z[3] == P3 && Nat128.Gte(z, P))) + if (c != 0 || (z[3] >= P3 && Nat128.Gte(z, P))) { AddPInvTo(z); } @@ -46,7 +46,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public static uint[] FromBigInteger(BigInteger x) { uint[] z = Nat128.FromBigInteger(x); - if (z[3] == P3 && Nat128.Gte(z, P)) + if (z[3] >= P3 && Nat128.Gte(z, P)) { Nat128.SubFrom(P, z); } @@ -76,7 +76,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public static void MultiplyAddToExt(uint[] x, uint[] y, uint[] zz) { uint c = Nat128.MulAddTo(x, y, zz); - if (c != 0 || (zz[7] == PExt7 && Nat256.Gte(zz, PExt))) + if (c != 0 || (zz[7] >= PExt7 && Nat256.Gte(zz, PExt))) { Nat.AddTo(PExtInv.Length, PExtInv, zz); } @@ -179,7 +179,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public static void Twice(uint[] x, uint[] z) { uint c = Nat.ShiftUpBit(4, x, 0, z); - if (c != 0 || (z[3] == P3 && Nat128.Gte(z, P))) + if (c != 0 || (z[3] >= P3 && Nat128.Gte(z, P))) { AddPInvTo(z); } -- cgit 1.4.1 From 9b3549d18ecc3e4f66488568594a626e7d6d8543 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sat, 3 Jun 2017 20:44:45 +0700 Subject: Initial implementation of SM2 elliptic curve - includes custom curve code - add lots of OIDs from GM standard --- crypto/BouncyCastle.Android.csproj | 6 + crypto/BouncyCastle.csproj | 6 + crypto/BouncyCastle.iOS.csproj | 6 + crypto/crypto.csproj | 30 ++ crypto/src/asn1/gm/GMNamedCurves.cs | 157 +++++++++++ crypto/src/asn1/gm/GMObjectIdentifiers.cs | 85 ++++++ crypto/src/asn1/x9/ECNamedCurveTable.cs | 31 ++- crypto/src/crypto/ec/CustomNamedCurves.cs | 25 ++ crypto/src/math/ec/custom/gm/SM2P256V1Curve.cs | 77 ++++++ crypto/src/math/ec/custom/gm/SM2P256V1Field.cs | 307 +++++++++++++++++++++ .../src/math/ec/custom/gm/SM2P256V1FieldElement.cs | 213 ++++++++++++++ crypto/src/math/ec/custom/gm/SM2P256V1Point.cs | 279 +++++++++++++++++++ crypto/test/src/test/NamedCurveTest.cs | 15 +- 13 files changed, 1221 insertions(+), 16 deletions(-) create mode 100644 crypto/src/asn1/gm/GMNamedCurves.cs create mode 100644 crypto/src/asn1/gm/GMObjectIdentifiers.cs create mode 100644 crypto/src/math/ec/custom/gm/SM2P256V1Curve.cs create mode 100644 crypto/src/math/ec/custom/gm/SM2P256V1Field.cs create mode 100644 crypto/src/math/ec/custom/gm/SM2P256V1FieldElement.cs create mode 100644 crypto/src/math/ec/custom/gm/SM2P256V1Point.cs (limited to 'crypto') diff --git a/crypto/BouncyCastle.Android.csproj b/crypto/BouncyCastle.Android.csproj index 541b534cd..ca279bf25 100644 --- a/crypto/BouncyCastle.Android.csproj +++ b/crypto/BouncyCastle.Android.csproj @@ -292,6 +292,8 @@ + + @@ -1117,6 +1119,10 @@ + + + + diff --git a/crypto/BouncyCastle.csproj b/crypto/BouncyCastle.csproj index 31910f963..387dd0835 100644 --- a/crypto/BouncyCastle.csproj +++ b/crypto/BouncyCastle.csproj @@ -286,6 +286,8 @@ + + @@ -1111,6 +1113,10 @@ + + + + diff --git a/crypto/BouncyCastle.iOS.csproj b/crypto/BouncyCastle.iOS.csproj index f9269337a..fb15014e3 100644 --- a/crypto/BouncyCastle.iOS.csproj +++ b/crypto/BouncyCastle.iOS.csproj @@ -287,6 +287,8 @@ + + @@ -1112,6 +1114,10 @@ + + + + diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index fe6b5fa1c..90b858cb0 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -1318,6 +1318,16 @@ SubType = "Code" BuildAction = "Compile" /> + + + + + + = P7 && Nat256.Gte(z, P))) + { + AddPInvTo(z); + } + } + + public static void AddExt(uint[] xx, uint[] yy, uint[] zz) + { + uint c = Nat.Add(16, xx, yy, zz); + if (c != 0 || (zz[15] >= PExt15 && Nat.Gte(16, zz, PExt))) + { + Nat.SubFrom(16, PExt, zz); + } + } + + public static void AddOne(uint[] x, uint[] z) + { + uint c = Nat.Inc(8, x, z); + if (c != 0 || (z[7] >= P7 && Nat256.Gte(z, P))) + { + AddPInvTo(z); + } + } + + public static uint[] FromBigInteger(BigInteger x) + { + uint[] z = Nat256.FromBigInteger(x); + if (z[7] >= P7 && Nat256.Gte(z, P)) + { + Nat256.SubFrom(P, z); + } + return z; + } + + public static void Half(uint[] x, uint[] z) + { + if ((x[0] & 1) == 0) + { + Nat.ShiftDownBit(8, x, 0, z); + } + else + { + uint c = Nat256.Add(x, P, z); + Nat.ShiftDownBit(8, z, c); + } + } + + public static void Multiply(uint[] x, uint[] y, uint[] z) + { + uint[] tt = Nat256.CreateExt(); + Nat256.Mul(x, y, tt); + Reduce(tt, z); + } + + public static void MultiplyAddToExt(uint[] x, uint[] y, uint[] zz) + { + uint c = Nat256.MulAddTo(x, y, zz); + if (c != 0 || (zz[15] >= PExt15 && Nat.Gte(16, zz, PExt))) + { + Nat.SubFrom(16, PExt, zz); + } + } + + public static void Negate(uint[] x, uint[] z) + { + if (Nat256.IsZero(x)) + { + Nat256.Zero(z); + } + else + { + Nat256.Sub(P, x, z); + } + } + + public static void Reduce(uint[] xx, uint[] z) + { + long xx08 = xx[8], xx09 = xx[9], xx10 = xx[10], xx11 = xx[11]; + long xx12 = xx[12], xx13 = xx[13], xx14 = xx[14], xx15 = xx[15]; + + long t0 = xx08 + xx09; + long t1 = xx10 + xx11; + long t2 = xx12 + xx15; + long t3 = xx13 + xx14; + long t4 = t3 + (xx15 << 1); + + long ts = t0 + t3; + long tt = t1 + t2 + ts; + + long cc = 0; + cc += (long)xx[0] + tt + xx13 + xx14 + xx15; + z[0] = (uint)cc; + cc >>= 32; + cc += (long)xx[1] + tt - xx08 + xx14 + xx15; + z[1] = (uint)cc; + cc >>= 32; + cc += (long)xx[2] - ts; + z[2] = (uint)cc; + cc >>= 32; + cc += (long)xx[3] + tt - xx09 - xx10 + xx13; + z[3] = (uint)cc; + cc >>= 32; + cc += (long)xx[4] + tt - t1 - xx08 + xx14; + z[4] = (uint)cc; + cc >>= 32; + cc += (long)xx[5] + t4 + xx10; + z[5] = (uint)cc; + cc >>= 32; + cc += (long)xx[6] + xx11 + xx14 + xx15; + z[6] = (uint)cc; + cc >>= 32; + cc += (long)xx[7] + tt + t4 + xx12; + z[7] = (uint)cc; + cc >>= 32; + + Debug.Assert(cc >= 0); + + Reduce32((uint)cc, z); + } + + public static void Reduce32(uint x, uint[] z) + { + long cc = 0; + + if (x != 0) + { + long xx08 = x; + + cc += (long)z[0] + xx08; + z[0] = (uint)cc; + cc >>= 32; + if (cc != 0) + { + cc += (long)z[1]; + z[1] = (uint)cc; + cc >>= 32; + } + cc += (long)z[2] - xx08; + z[2] = (uint)cc; + cc >>= 32; + cc += (long)z[3] + xx08; + z[3] = (uint)cc; + cc >>= 32; + if (cc != 0) + { + cc += (long)z[4]; + z[4] = (uint)cc; + cc >>= 32; + cc += (long)z[5]; + z[5] = (uint)cc; + cc >>= 32; + cc += (long)z[6]; + z[6] = (uint)cc; + cc >>= 32; + } + cc += (long)z[7] + xx08; + z[7] = (uint)cc; + cc >>= 32; + + Debug.Assert(cc == 0 || cc == 1); + } + + if (cc != 0 || (z[7] >= P7 && Nat256.Gte(z, P))) + { + AddPInvTo(z); + } + } + + public static void Square(uint[] x, uint[] z) + { + uint[] tt = Nat256.CreateExt(); + Nat256.Square(x, tt); + Reduce(tt, z); + } + + public static void SquareN(uint[] x, int n, uint[] z) + { + Debug.Assert(n > 0); + + uint[] tt = Nat256.CreateExt(); + Nat256.Square(x, tt); + Reduce(tt, z); + + while (--n > 0) + { + Nat256.Square(z, tt); + Reduce(tt, z); + } + } + + public static void Subtract(uint[] x, uint[] y, uint[] z) + { + int c = Nat256.Sub(x, y, z); + if (c != 0) + { + SubPInvFrom(z); + } + } + + public static void SubtractExt(uint[] xx, uint[] yy, uint[] zz) + { + int c = Nat.Sub(16, xx, yy, zz); + if (c != 0) + { + Nat.AddTo(16, PExt, zz); + } + } + + public static void Twice(uint[] x, uint[] z) + { + uint c = Nat.ShiftUpBit(8, x, 0, z); + if (c != 0 || (z[7] >= P7 && Nat256.Gte(z, P))) + { + AddPInvTo(z); + } + } + + private static void AddPInvTo(uint[] z) + { + long c = (long)z[0] + 1; + z[0] = (uint)c; + c >>= 32; + if (c != 0) + { + c += (long)z[1]; + z[1] = (uint)c; + c >>= 32; + } + c += (long)z[2] - 1; + z[2] = (uint)c; + c >>= 32; + c += (long)z[3] + 1; + z[3] = (uint)c; + c >>= 32; + if (c != 0) + { + c += (long)z[4]; + z[4] = (uint)c; + c >>= 32; + c += (long)z[5]; + z[5] = (uint)c; + c >>= 32; + c += (long)z[6]; + z[6] = (uint)c; + c >>= 32; + } + c += (long)z[7] + 1; + z[7] = (uint)c; + //c >>= 32; + } + + private static void SubPInvFrom(uint[] z) + { + long c = (long)z[0] - 1; + z[0] = (uint)c; + c >>= 32; + if (c != 0) + { + c += (long)z[1]; + z[1] = (uint)c; + c >>= 32; + } + c += (long)z[2] + 1; + z[2] = (uint)c; + c >>= 32; + c += (long)z[3] - 1; + z[3] = (uint)c; + c >>= 32; + if (c != 0) + { + c += (long)z[4]; + z[4] = (uint)c; + c >>= 32; + c += (long)z[5]; + z[5] = (uint)c; + c >>= 32; + c += (long)z[6]; + z[6] = (uint)c; + c >>= 32; + } + c += (long)z[7] - 1; + z[7] = (uint)c; + //c >>= 32; + } + } +} diff --git a/crypto/src/math/ec/custom/gm/SM2P256V1FieldElement.cs b/crypto/src/math/ec/custom/gm/SM2P256V1FieldElement.cs new file mode 100644 index 000000000..669c73bd2 --- /dev/null +++ b/crypto/src/math/ec/custom/gm/SM2P256V1FieldElement.cs @@ -0,0 +1,213 @@ +using System; + +using Org.BouncyCastle.Math.Raw; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Math.EC.Custom.GM +{ + internal class SM2P256V1FieldElement + : ECFieldElement + { + public static readonly BigInteger Q = SM2P256V1Curve.q; + + protected internal readonly uint[] x; + + public SM2P256V1FieldElement(BigInteger x) + { + if (x == null || x.SignValue < 0 || x.CompareTo(Q) >= 0) + throw new ArgumentException("value invalid for SM2P256V1FieldElement", "x"); + + this.x = SM2P256V1Field.FromBigInteger(x); + } + + public SM2P256V1FieldElement() + { + this.x = Nat256.Create(); + } + + protected internal SM2P256V1FieldElement(uint[] x) + { + this.x = x; + } + + public override bool IsZero + { + get { return Nat256.IsZero(x); } + } + + public override bool IsOne + { + get { return Nat256.IsOne(x); } + } + + public override bool TestBitZero() + { + return Nat256.GetBit(x, 0) == 1; + } + + public override BigInteger ToBigInteger() + { + return Nat256.ToBigInteger(x); + } + + public override string FieldName + { + get { return "SM2P256V1Field"; } + } + + public override int FieldSize + { + get { return Q.BitLength; } + } + + public override ECFieldElement Add(ECFieldElement b) + { + uint[] z = Nat256.Create(); + SM2P256V1Field.Add(x, ((SM2P256V1FieldElement)b).x, z); + return new SM2P256V1FieldElement(z); + } + + public override ECFieldElement AddOne() + { + uint[] z = Nat256.Create(); + SM2P256V1Field.AddOne(x, z); + return new SM2P256V1FieldElement(z); + } + + public override ECFieldElement Subtract(ECFieldElement b) + { + uint[] z = Nat256.Create(); + SM2P256V1Field.Subtract(x, ((SM2P256V1FieldElement)b).x, z); + return new SM2P256V1FieldElement(z); + } + + public override ECFieldElement Multiply(ECFieldElement b) + { + uint[] z = Nat256.Create(); + SM2P256V1Field.Multiply(x, ((SM2P256V1FieldElement)b).x, z); + return new SM2P256V1FieldElement(z); + } + + public override ECFieldElement Divide(ECFieldElement b) + { + //return Multiply(b.Invert()); + uint[] z = Nat256.Create(); + Mod.Invert(SM2P256V1Field.P, ((SM2P256V1FieldElement)b).x, z); + SM2P256V1Field.Multiply(z, x, z); + return new SM2P256V1FieldElement(z); + } + + public override ECFieldElement Negate() + { + uint[] z = Nat256.Create(); + SM2P256V1Field.Negate(x, z); + return new SM2P256V1FieldElement(z); + } + + public override ECFieldElement Square() + { + uint[] z = Nat256.Create(); + SM2P256V1Field.Square(x, z); + return new SM2P256V1FieldElement(z); + } + + public override ECFieldElement Invert() + { + //return new SM2P256V1FieldElement(ToBigInteger().ModInverse(Q)); + uint[] z = Nat256.Create(); + Mod.Invert(SM2P256V1Field.P, x, z); + return new SM2P256V1FieldElement(z); + } + + /** + * return a sqrt root - the routine verifies that the calculation returns the right value - if + * none exists it returns null. + */ + public override ECFieldElement Sqrt() + { + /* + * Raise this element to the exponent 2^254 - 2^222 - 2^94 + 2^62 + * + * Breaking up the exponent's binary representation into "repunits", we get: + * { 31 1s } { 1 0s } { 128 1s } { 31 0s } { 1 1s } { 62 0s} + * + * We use an addition chain for the beginning: [1], 2, 3, 6, 12, [24], 30, [31] + */ + + uint[] x1 = this.x; + if (Nat256.IsZero(x1) || Nat256.IsOne(x1)) + { + return this; + } + + uint[] x2 = Nat256.Create(); + SM2P256V1Field.Square(x1, x2); + SM2P256V1Field.Multiply(x2, x1, x2); + uint[] x3 = x2; + SM2P256V1Field.Square(x2, x3); + SM2P256V1Field.Multiply(x3, x1, x3); + uint[] x6 = Nat256.Create(); + SM2P256V1Field.SquareN(x3, 3, x6); + SM2P256V1Field.Multiply(x6, x3, x6); + uint[] x12 = x3; + SM2P256V1Field.SquareN(x6, 6, x12); + SM2P256V1Field.Multiply(x12, x6, x12); + uint[] x24 = Nat256.Create(); + SM2P256V1Field.SquareN(x12, 12, x24); + SM2P256V1Field.Multiply(x24, x12, x24); + uint[] x30 = x12; + SM2P256V1Field.SquareN(x24, 6, x30); + SM2P256V1Field.Multiply(x30, x6, x30); + uint[] x31 = x6; + SM2P256V1Field.Square(x30, x31); + SM2P256V1Field.Multiply(x31, x1, x31); + + uint[] t1 = x31; + SM2P256V1Field.Square(x31, t1); + + uint[] x32 = x12; + SM2P256V1Field.Multiply(t1, x1, x32); + + SM2P256V1Field.SquareN(t1, 32, t1); + SM2P256V1Field.Multiply(t1, x32, t1); + + uint[] t2 = x24; + SM2P256V1Field.SquareN(t1, 32, t2); + SM2P256V1Field.Multiply(t2, x1, t2); + SM2P256V1Field.SquareN(t2, 32, t2); + SM2P256V1Field.Multiply(t2, t1, t2); + SM2P256V1Field.SquareN(t2, 32, t2); + SM2P256V1Field.Multiply(t2, x32, t2); + SM2P256V1Field.SquareN(t2, 32, t2); + SM2P256V1Field.Multiply(t2, x1, t2); + SM2P256V1Field.SquareN(t2, 62, t1); + SM2P256V1Field.Square(t1, t2); + + return Nat256.Eq(x1, t2) ? new SM2P256V1FieldElement(t1) : null; + } + + public override bool Equals(object obj) + { + return Equals(obj as SM2P256V1FieldElement); + } + + public override bool Equals(ECFieldElement other) + { + return Equals(other as SM2P256V1FieldElement); + } + + public virtual bool Equals(SM2P256V1FieldElement other) + { + if (this == other) + return true; + if (null == other) + return false; + return Nat256.Eq(x, other.x); + } + + public override int GetHashCode() + { + return Q.GetHashCode() ^ Arrays.GetHashCode(x, 0, 8); + } + } +} diff --git a/crypto/src/math/ec/custom/gm/SM2P256V1Point.cs b/crypto/src/math/ec/custom/gm/SM2P256V1Point.cs new file mode 100644 index 000000000..916c90633 --- /dev/null +++ b/crypto/src/math/ec/custom/gm/SM2P256V1Point.cs @@ -0,0 +1,279 @@ +using System; + +using Org.BouncyCastle.Math.Raw; + +namespace Org.BouncyCastle.Math.EC.Custom.GM +{ + internal class SM2P256V1Point + : AbstractFpPoint + { + /** + * Create a point which encodes with point compression. + * + * @param curve + * the curve to use + * @param x + * affine x co-ordinate + * @param y + * affine y co-ordinate + * + * @deprecated Use ECCurve.createPoint to construct points + */ + public SM2P256V1Point(ECCurve curve, ECFieldElement x, ECFieldElement y) + : this(curve, x, y, false) + { + } + + /** + * Create a point that encodes with or without point compresion. + * + * @param curve + * the curve to use + * @param x + * affine x co-ordinate + * @param y + * affine y co-ordinate + * @param withCompression + * if true encode with point compression + * + * @deprecated per-point compression property will be removed, refer + * {@link #getEncoded(bool)} + */ + public SM2P256V1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) + : base(curve, x, y, withCompression) + { + if ((x == null) != (y == null)) + throw new ArgumentException("Exactly one of the field elements is null"); + } + + internal SM2P256V1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + : base(curve, x, y, zs, withCompression) + { + } + + protected override ECPoint Detach() + { + return new SM2P256V1Point(null, AffineXCoord, AffineYCoord); + } + + public override ECPoint Add(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return this; + if (this == b) + return Twice(); + + ECCurve curve = this.Curve; + + SM2P256V1FieldElement X1 = (SM2P256V1FieldElement)this.RawXCoord, Y1 = (SM2P256V1FieldElement)this.RawYCoord; + SM2P256V1FieldElement X2 = (SM2P256V1FieldElement)b.RawXCoord, Y2 = (SM2P256V1FieldElement)b.RawYCoord; + + SM2P256V1FieldElement Z1 = (SM2P256V1FieldElement)this.RawZCoords[0]; + SM2P256V1FieldElement Z2 = (SM2P256V1FieldElement)b.RawZCoords[0]; + + uint c; + uint[] tt1 = Nat256.CreateExt(); + uint[] t2 = Nat256.Create(); + uint[] t3 = Nat256.Create(); + uint[] t4 = Nat256.Create(); + + bool Z1IsOne = Z1.IsOne; + uint[] U2, S2; + if (Z1IsOne) + { + U2 = X2.x; + S2 = Y2.x; + } + else + { + S2 = t3; + SM2P256V1Field.Square(Z1.x, S2); + + U2 = t2; + SM2P256V1Field.Multiply(S2, X2.x, U2); + + SM2P256V1Field.Multiply(S2, Z1.x, S2); + SM2P256V1Field.Multiply(S2, Y2.x, S2); + } + + bool Z2IsOne = Z2.IsOne; + uint[] U1, S1; + if (Z2IsOne) + { + U1 = X1.x; + S1 = Y1.x; + } + else + { + S1 = t4; + SM2P256V1Field.Square(Z2.x, S1); + + U1 = tt1; + SM2P256V1Field.Multiply(S1, X1.x, U1); + + SM2P256V1Field.Multiply(S1, Z2.x, S1); + SM2P256V1Field.Multiply(S1, Y1.x, S1); + } + + uint[] H = Nat256.Create(); + SM2P256V1Field.Subtract(U1, U2, H); + + uint[] R = t2; + SM2P256V1Field.Subtract(S1, S2, R); + + // Check if b == this or b == -this + if (Nat256.IsZero(H)) + { + if (Nat256.IsZero(R)) + { + // this == b, i.e. this must be doubled + return this.Twice(); + } + + // this == -b, i.e. the result is the point at infinity + return curve.Infinity; + } + + uint[] HSquared = t3; + SM2P256V1Field.Square(H, HSquared); + + uint[] G = Nat256.Create(); + SM2P256V1Field.Multiply(HSquared, H, G); + + uint[] V = t3; + SM2P256V1Field.Multiply(HSquared, U1, V); + + SM2P256V1Field.Negate(G, G); + Nat256.Mul(S1, G, tt1); + + c = Nat256.AddBothTo(V, V, G); + SM2P256V1Field.Reduce32(c, G); + + SM2P256V1FieldElement X3 = new SM2P256V1FieldElement(t4); + SM2P256V1Field.Square(R, X3.x); + SM2P256V1Field.Subtract(X3.x, G, X3.x); + + SM2P256V1FieldElement Y3 = new SM2P256V1FieldElement(G); + SM2P256V1Field.Subtract(V, X3.x, Y3.x); + SM2P256V1Field.MultiplyAddToExt(Y3.x, R, tt1); + SM2P256V1Field.Reduce(tt1, Y3.x); + + SM2P256V1FieldElement Z3 = new SM2P256V1FieldElement(H); + if (!Z1IsOne) + { + SM2P256V1Field.Multiply(Z3.x, Z1.x, Z3.x); + } + if (!Z2IsOne) + { + SM2P256V1Field.Multiply(Z3.x, Z2.x, Z3.x); + } + + ECFieldElement[] zs = new ECFieldElement[]{ Z3 }; + + return new SM2P256V1Point(curve, X3, Y3, zs, IsCompressed); + } + + public override ECPoint Twice() + { + if (this.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + SM2P256V1FieldElement Y1 = (SM2P256V1FieldElement)this.RawYCoord; + if (Y1.IsZero) + return curve.Infinity; + + SM2P256V1FieldElement X1 = (SM2P256V1FieldElement)this.RawXCoord, Z1 = (SM2P256V1FieldElement)this.RawZCoords[0]; + + uint c; + uint[] t1 = Nat256.Create(); + uint[] t2 = Nat256.Create(); + + uint[] Y1Squared = Nat256.Create(); + SM2P256V1Field.Square(Y1.x, Y1Squared); + + uint[] T = Nat256.Create(); + SM2P256V1Field.Square(Y1Squared, T); + + bool Z1IsOne = Z1.IsOne; + + uint[] Z1Squared = Z1.x; + if (!Z1IsOne) + { + Z1Squared = t2; + SM2P256V1Field.Square(Z1.x, Z1Squared); + } + + SM2P256V1Field.Subtract(X1.x, Z1Squared, t1); + + uint[] M = t2; + SM2P256V1Field.Add(X1.x, Z1Squared, M); + SM2P256V1Field.Multiply(M, t1, M); + c = Nat256.AddBothTo(M, M, M); + SM2P256V1Field.Reduce32(c, M); + + uint[] S = Y1Squared; + SM2P256V1Field.Multiply(Y1Squared, X1.x, S); + c = Nat.ShiftUpBits(8, S, 2, 0); + SM2P256V1Field.Reduce32(c, S); + + c = Nat.ShiftUpBits(8, T, 3, 0, t1); + SM2P256V1Field.Reduce32(c, t1); + + SM2P256V1FieldElement X3 = new SM2P256V1FieldElement(T); + SM2P256V1Field.Square(M, X3.x); + SM2P256V1Field.Subtract(X3.x, S, X3.x); + SM2P256V1Field.Subtract(X3.x, S, X3.x); + + SM2P256V1FieldElement Y3 = new SM2P256V1FieldElement(S); + SM2P256V1Field.Subtract(S, X3.x, Y3.x); + SM2P256V1Field.Multiply(Y3.x, M, Y3.x); + SM2P256V1Field.Subtract(Y3.x, t1, Y3.x); + + SM2P256V1FieldElement Z3 = new SM2P256V1FieldElement(M); + SM2P256V1Field.Twice(Y1.x, Z3.x); + if (!Z1IsOne) + { + SM2P256V1Field.Multiply(Z3.x, Z1.x, Z3.x); + } + + return new SM2P256V1Point(curve, X3, Y3, new ECFieldElement[]{ Z3 }, IsCompressed); + } + + public override ECPoint TwicePlus(ECPoint b) + { + if (this == b) + return ThreeTimes(); + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return Twice(); + + ECFieldElement Y1 = this.RawYCoord; + if (Y1.IsZero) + return b; + + return Twice().Add(b); + } + + public override ECPoint ThreeTimes() + { + if (this.IsInfinity || this.RawYCoord.IsZero) + return this; + + // NOTE: Be careful about recursions between TwicePlus and ThreeTimes + return Twice().Add(this); + } + + public override ECPoint Negate() + { + if (IsInfinity) + return this; + + return new SM2P256V1Point(Curve, RawXCoord, RawYCoord.Negate(), RawZCoords, IsCompressed); + } + } +} diff --git a/crypto/test/src/test/NamedCurveTest.cs b/crypto/test/src/test/NamedCurveTest.cs index bc8684aa5..2d2758b58 100644 --- a/crypto/test/src/test/NamedCurveTest.cs +++ b/crypto/test/src/test/NamedCurveTest.cs @@ -1,11 +1,10 @@ using System; -using System.Collections; using NUnit.Framework; -using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Anssi; using Org.BouncyCastle.Asn1.CryptoPro; -using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.GM; using Org.BouncyCastle.Asn1.Sec; using Org.BouncyCastle.Asn1.TeleTrust; using Org.BouncyCastle.Asn1.X9; @@ -358,6 +357,16 @@ namespace Org.BouncyCastle.Tests doTestECDsa(name); } + foreach (string name in AnssiNamedCurves.Names) + { + doTestECDsa(name); + } + + foreach (string name in GMNamedCurves.Names) + { + doTestECDsa(name); + } + foreach (string name in ECGost3410NamedCurves.Names) { doTestECGost(name); -- cgit 1.4.1 From e4fba9b8f4c4f876d0dc470ed3cbe7066f939cd3 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Tue, 6 Jun 2017 12:06:38 +0700 Subject: Fix paths for previous commit --- crypto/crypto.csproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'crypto') diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index 90b858cb0..ab7413788 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -5454,22 +5454,22 @@ BuildAction = "Compile" /> -- cgit 1.4.1 From 4589defc7197db8d49edc67a354a34ce2ce5928b Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Wed, 7 Jun 2017 14:40:24 +0700 Subject: Specific exception TlsFatalAlertReceived for peer fatal alerts --- crypto/BouncyCastle.Android.csproj | 2 ++ crypto/BouncyCastle.csproj | 2 ++ crypto/BouncyCastle.iOS.csproj | 2 ++ crypto/crypto.csproj | 10 ++++++++ crypto/src/crypto/tls/TlsException.cs | 14 +++++++++++ crypto/src/crypto/tls/TlsFatalAlert.cs | 3 +-- crypto/src/crypto/tls/TlsFatalAlertReceived.cs | 21 +++++++++++++++++ crypto/src/crypto/tls/TlsProtocol.cs | 32 ++++++++++++-------------- 8 files changed, 67 insertions(+), 19 deletions(-) create mode 100644 crypto/src/crypto/tls/TlsException.cs create mode 100644 crypto/src/crypto/tls/TlsFatalAlertReceived.cs (limited to 'crypto') diff --git a/crypto/BouncyCastle.Android.csproj b/crypto/BouncyCastle.Android.csproj index ca279bf25..921331f9a 100644 --- a/crypto/BouncyCastle.Android.csproj +++ b/crypto/BouncyCastle.Android.csproj @@ -1064,8 +1064,10 @@ + + diff --git a/crypto/BouncyCastle.csproj b/crypto/BouncyCastle.csproj index 387dd0835..ed2ce50ad 100644 --- a/crypto/BouncyCastle.csproj +++ b/crypto/BouncyCastle.csproj @@ -1058,8 +1058,10 @@ + + diff --git a/crypto/BouncyCastle.iOS.csproj b/crypto/BouncyCastle.iOS.csproj index fb15014e3..8d5d3032f 100644 --- a/crypto/BouncyCastle.iOS.csproj +++ b/crypto/BouncyCastle.iOS.csproj @@ -1059,8 +1059,10 @@ + + diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index ab7413788..026a2fe1b 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -5178,6 +5178,11 @@ SubType = "Code" BuildAction = "Compile" /> + + Date: Thu, 8 Jun 2017 14:11:29 +0700 Subject: Add latest extension type values from IANA registry --- crypto/src/crypto/tls/ExtensionType.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'crypto') diff --git a/crypto/src/crypto/tls/ExtensionType.cs b/crypto/src/crypto/tls/ExtensionType.cs index bff9332a0..f17210b80 100644 --- a/crypto/src/crypto/tls/ExtensionType.cs +++ b/crypto/src/crypto/tls/ExtensionType.cs @@ -98,6 +98,16 @@ namespace Org.BouncyCastle.Crypto.Tls */ public const int extended_master_secret = 23; + /* + * draft-ietf-tokbind-negotiation-08 + */ + public static readonly int DRAFT_token_binding = 24; + + /* + * RFC 7924 + */ + public const int cached_info = 25; + /* * RFC 5077 7. */ -- cgit 1.4.1 From 08629c3971a95d19e431c5cdb38cccbb8e5f79c0 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Thu, 8 Jun 2017 19:00:24 +0700 Subject: Add explicit limit for sequence numbers --- crypto/src/crypto/tls/RecordStream.cs | 36 +++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/tls/RecordStream.cs b/crypto/src/crypto/tls/RecordStream.cs index 46673cf7e..5d556ad06 100644 --- a/crypto/src/crypto/tls/RecordStream.cs +++ b/crypto/src/crypto/tls/RecordStream.cs @@ -21,7 +21,7 @@ namespace Org.BouncyCastle.Crypto.Tls private Stream mOutput; private TlsCompression mPendingCompression = null, mReadCompression = null, mWriteCompression = null; private TlsCipher mPendingCipher = null, mReadCipher = null, mWriteCipher = null; - private long mReadSeqNo = 0, mWriteSeqNo = 0; + private SequenceNumber mReadSeqNo = new SequenceNumber(), mWriteSeqNo = new SequenceNumber(); private MemoryStream mBuffer = new MemoryStream(); private TlsHandshakeHash mHandshakeHash = null; @@ -100,7 +100,7 @@ namespace Org.BouncyCastle.Crypto.Tls this.mWriteCompression = this.mPendingCompression; this.mWriteCipher = this.mPendingCipher; - this.mWriteSeqNo = 0; + this.mWriteSeqNo = new SequenceNumber(); } internal virtual void ReceivedReadCipherSpec() @@ -110,7 +110,7 @@ namespace Org.BouncyCastle.Crypto.Tls this.mReadCompression = this.mPendingCompression; this.mReadCipher = this.mPendingCipher; - this.mReadSeqNo = 0; + this.mReadSeqNo = new SequenceNumber(); } internal virtual void FinaliseHandshake() @@ -203,7 +203,9 @@ namespace Org.BouncyCastle.Crypto.Tls internal virtual byte[] DecodeAndVerify(byte type, Stream input, int len) { byte[] buf = TlsUtilities.ReadFully(len, input); - byte[] decoded = mReadCipher.DecodeCiphertext(mReadSeqNo++, type, buf, 0, buf.Length); + + long seqNo = mReadSeqNo.NextValue(AlertDescription.unexpected_message); + byte[] decoded = mReadCipher.DecodeCiphertext(seqNo, type, buf, 0, buf.Length); CheckLength(decoded.Length, mCompressedLimit, AlertDescription.record_overflow); @@ -262,10 +264,12 @@ namespace Org.BouncyCastle.Crypto.Tls Stream cOut = mWriteCompression.Compress(mBuffer); + long seqNo = mWriteSeqNo.NextValue(AlertDescription.internal_error); + byte[] ciphertext; if (cOut == mBuffer) { - ciphertext = mWriteCipher.EncodePlaintext(mWriteSeqNo++, type, plaintext, plaintextOffset, plaintextLength); + ciphertext = mWriteCipher.EncodePlaintext(seqNo, type, plaintext, plaintextOffset, plaintextLength); } else { @@ -279,7 +283,7 @@ namespace Org.BouncyCastle.Crypto.Tls */ CheckLength(compressed.Length, plaintextLength + 1024, AlertDescription.internal_error); - ciphertext = mWriteCipher.EncodePlaintext(mWriteSeqNo++, type, compressed, 0, compressed.Length); + ciphertext = mWriteCipher.EncodePlaintext(seqNo, type, compressed, 0, compressed.Length); } /* @@ -384,5 +388,25 @@ namespace Org.BouncyCastle.Crypto.Tls mOuter.mHandshakeHash.BlockUpdate(buf, off, len); } } + + private class SequenceNumber + { + private long value = 0L; + private bool exhausted = false; + + internal long NextValue(byte alertDescription) + { + if (exhausted) + { + throw new TlsFatalAlert(alertDescription); + } + long result = value; + if (++value == 0) + { + exhausted = true; + } + return result; + } + } } } -- cgit 1.4.1 From 53a508e381f21061c8c6f49f8c19c703faab2a38 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 9 Jun 2017 12:36:38 +0700 Subject: Improved header control in ArmoredOutputStream - in particular, supports removing the default version header --- crypto/src/bcpg/ArmoredOutputStream.cs | 47 ++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 14 deletions(-) (limited to 'crypto') diff --git a/crypto/src/bcpg/ArmoredOutputStream.cs b/crypto/src/bcpg/ArmoredOutputStream.cs index 1f0e412d8..dae6b98e5 100644 --- a/crypto/src/bcpg/ArmoredOutputStream.cs +++ b/crypto/src/bcpg/ArmoredOutputStream.cs @@ -20,6 +20,8 @@ namespace Org.BouncyCastle.Bcpg public class ArmoredOutputStream : BaseOutputStream { + public static readonly string HeaderVersion = "Version"; + private static readonly byte[] encodingTable = { (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', @@ -101,35 +103,43 @@ namespace Org.BouncyCastle.Bcpg private static readonly string footerStart = "-----END PGP "; private static readonly string footerTail = "-----"; - private static readonly string version = "BCPG C# v" + AssemblyInfo.Version; + private static readonly string Version = "BCPG C# v" + AssemblyInfo.Version; private readonly IDictionary headers; public ArmoredOutputStream(Stream outStream) { this.outStream = outStream; - this.headers = Platform.CreateHashtable(); - this.headers["Version"] = version; + this.headers = Platform.CreateHashtable(1); + this.headers.Add(HeaderVersion, Version); } public ArmoredOutputStream(Stream outStream, IDictionary headers) { this.outStream = outStream; this.headers = Platform.CreateHashtable(headers); - this.headers["Version"] = version; + if (!this.headers.Contains(HeaderVersion)) + { + this.headers.Add(HeaderVersion, Version); + } } /** - * Set an additional header entry. + * Set an additional header entry. A null value will clear the entry for name. * * @param name the name of the header entry. * @param v the value of the header entry. */ - public void SetHeader( - string name, - string v) + public void SetHeader(string name, string v) { - headers[name] = v; + if (v == null) + { + headers.Remove(name); + } + else + { + headers[name] = v; + } } /** @@ -137,8 +147,14 @@ namespace Org.BouncyCastle.Bcpg */ public void ResetHeaders() { + string version = (string)headers[HeaderVersion]; + headers.Clear(); - headers["Version"] = version; + + if (version != null) + { + headers[HeaderVersion] = Version; + } } /** @@ -248,14 +264,17 @@ namespace Org.BouncyCastle.Bcpg } DoWrite(headerStart + type + headerTail + nl); - WriteHeaderEntry("Version", (string) headers["Version"]); + if (headers.Contains(HeaderVersion)) + { + WriteHeaderEntry(HeaderVersion, (string)headers[HeaderVersion]); + } foreach (DictionaryEntry de in headers) { - string k = (string) de.Key; - if (k != "Version") + string k = (string)de.Key; + if (k != HeaderVersion) { - string v = (string) de.Value; + string v = (string)de.Value; WriteHeaderEntry(k, v); } } -- cgit 1.4.1 From ad4984a18872b8540b48d21207d7cb3bb622aa74 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 9 Jun 2017 12:57:45 +0700 Subject: Comments --- crypto/src/bcpg/ArmoredOutputStream.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/src/bcpg/ArmoredOutputStream.cs b/crypto/src/bcpg/ArmoredOutputStream.cs index dae6b98e5..7a5066ec3 100644 --- a/crypto/src/bcpg/ArmoredOutputStream.cs +++ b/crypto/src/bcpg/ArmoredOutputStream.cs @@ -143,7 +143,7 @@ namespace Org.BouncyCastle.Bcpg } /** - * Reset the headers to only contain a Version string. + * Reset the headers to only contain a Version string (if one is present). */ public void ResetHeaders() { -- cgit 1.4.1 From b5b1ad3e9abdaada947513b5a4940e93c4aae210 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 9 Jun 2017 12:58:17 +0700 Subject: Add explicit length check on OAEP input --- crypto/src/crypto/encodings/OaepEncoding.cs | 2 ++ crypto/test/src/crypto/test/RsaTest.cs | 29 +++++++++++++++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/encodings/OaepEncoding.cs b/crypto/src/crypto/encodings/OaepEncoding.cs index cb23b1710..9f5c563c2 100644 --- a/crypto/src/crypto/encodings/OaepEncoding.cs +++ b/crypto/src/crypto/encodings/OaepEncoding.cs @@ -137,6 +137,8 @@ namespace Org.BouncyCastle.Crypto.Encodings int inOff, int inLen) { + Check.DataLength(inLen > GetInputBlockSize(), "input data too long"); + byte[] block = new byte[GetInputBlockSize() + 1 + 2 * defHash.Length]; // diff --git a/crypto/test/src/crypto/test/RsaTest.cs b/crypto/test/src/crypto/test/RsaTest.cs index c343f0ba5..d0cbedace 100644 --- a/crypto/test/src/crypto/test/RsaTest.cs +++ b/crypto/test/src/crypto/test/RsaTest.cs @@ -192,13 +192,34 @@ namespace Org.BouncyCastle.Crypto.Tests { Fail("failed OAEP Test"); } - } - // TODO Move this when other JCE tests are ported from Java - /** + // check for oversized input + byte[] message = new byte[87]; + RsaEngine rsaEngine = new RsaEngine(); + IAsymmetricBlockCipher cipher = new OaepEncoding(rsaEngine, new Sha1Digest(), new Sha1Digest(), message); + cipher.Init(true, new ParametersWithRandom(pubParameters, new SecureRandom())); + + try + { + cipher.ProcessBlock(message, 0, message.Length); + + Fail("no exception thrown"); + } + catch (DataLengthException e) + { + IsTrue("message mismatch", "input data too long".Equals(e.Message)); + } + catch (InvalidCipherTextException e) + { + Fail("failed - exception " + e.ToString(), e); + } + } + + // TODO Move this when other JCE tests are ported from Java + /** * signature with a "forged signature" (sig block not at end of plain text) */ - private void doTestBadSig()//PrivateKey priv, PublicKey pub) + private void doTestBadSig()//PrivateKey priv, PublicKey pub) { // Signature sig = Signature.getInstance("SHA1WithRSAEncryption", "BC"); ISigner sig = SignerUtilities.GetSigner("SHA1WithRSAEncryption"); -- cgit 1.4.1 From 58b2040d36be9f1271b93a7fae752dc8975a881e Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 9 Jun 2017 14:41:16 +0700 Subject: Add point validation to EC public key constructors --- .../src/crypto/parameters/ECPublicKeyParameters.cs | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/parameters/ECPublicKeyParameters.cs b/crypto/src/crypto/parameters/ECPublicKeyParameters.cs index 1eb665da9..474e5d82c 100644 --- a/crypto/src/crypto/parameters/ECPublicKeyParameters.cs +++ b/crypto/src/crypto/parameters/ECPublicKeyParameters.cs @@ -9,6 +9,21 @@ namespace Org.BouncyCastle.Crypto.Parameters public class ECPublicKeyParameters : ECKeyParameters { + private static ECPoint Validate(ECPoint q) + { + if (q == null) + throw new ArgumentNullException("q"); + if (q.IsInfinity) + throw new ArgumentException("point at infinity", "q"); + + q = q.Normalize(); + + if (!q.IsValid()) + throw new ArgumentException("point not on curve", "q"); + + return q; + } + private readonly ECPoint q; public ECPublicKeyParameters( @@ -27,7 +42,7 @@ namespace Org.BouncyCastle.Crypto.Parameters if (q == null) throw new ArgumentNullException("q"); - this.q = q.Normalize(); + this.q = Validate(q); } public ECPublicKeyParameters( @@ -39,7 +54,7 @@ namespace Org.BouncyCastle.Crypto.Parameters if (q == null) throw new ArgumentNullException("q"); - this.q = q.Normalize(); + this.q = Validate(q); } public ECPublicKeyParameters( @@ -51,7 +66,7 @@ namespace Org.BouncyCastle.Crypto.Parameters if (q == null) throw new ArgumentNullException("q"); - this.q = q.Normalize(); + this.q = Validate(q); } public ECPoint Q -- cgit 1.4.1 From dab58845745b1936666d91c0f2ccc47d5cb5c8a4 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 9 Jun 2017 14:56:27 +0700 Subject: Add validation to DSA public key constructor --- crypto/src/crypto/parameters/DsaPublicKeyParameters.cs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/src/crypto/parameters/DsaPublicKeyParameters.cs b/crypto/src/crypto/parameters/DsaPublicKeyParameters.cs index f11f858f3..3a81bfdd0 100644 --- a/crypto/src/crypto/parameters/DsaPublicKeyParameters.cs +++ b/crypto/src/crypto/parameters/DsaPublicKeyParameters.cs @@ -7,6 +7,22 @@ namespace Org.BouncyCastle.Crypto.Parameters public class DsaPublicKeyParameters : DsaKeyParameters { + private static BigInteger Validate(BigInteger y, DsaParameters parameters) + { + // we can't validate without params, fortunately we can't use the key either... + if (parameters != null) + { + if (y.CompareTo(BigInteger.Two) < 0 + || y.CompareTo(parameters.P.Subtract(BigInteger.Two)) > 0 + || !y.ModPow(parameters.Q, parameters.P).Equals(BigInteger.One)) + { + throw new ArgumentException("y value does not appear to be in correct group"); + } + } + + return y; + } + private readonly BigInteger y; public DsaPublicKeyParameters( @@ -17,7 +33,7 @@ namespace Org.BouncyCastle.Crypto.Parameters if (y == null) throw new ArgumentNullException("y"); - this.y = y; + this.y = Validate(y, parameters); } public BigInteger Y -- cgit 1.4.1 From a7e03daa1cb6604a945133427c7c9cfc5e08720c Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 9 Jun 2017 15:06:20 +0700 Subject: Add validation to DH public key constructor --- .../src/crypto/parameters/DHPublicKeyParameters.cs | 29 ++++++++++++++++------ 1 file changed, 21 insertions(+), 8 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/parameters/DHPublicKeyParameters.cs b/crypto/src/crypto/parameters/DHPublicKeyParameters.cs index e79375f71..1704c47dc 100644 --- a/crypto/src/crypto/parameters/DHPublicKeyParameters.cs +++ b/crypto/src/crypto/parameters/DHPublicKeyParameters.cs @@ -8,6 +8,25 @@ namespace Org.BouncyCastle.Crypto.Parameters public class DHPublicKeyParameters : DHKeyParameters { + private static BigInteger Validate(BigInteger y, DHParameters dhParams) + { + if (y == null) + throw new ArgumentNullException("y"); + + // TLS check + if (y.CompareTo(BigInteger.Two) < 0 || y.CompareTo(dhParams.P.Subtract(BigInteger.Two)) > 0) + throw new ArgumentException("invalid DH public key", "y"); + + // we can't validate without Q. + if (dhParams.Q != null + && !y.ModPow(dhParams.Q, dhParams.P).Equals(BigInteger.One)) + { + throw new ArgumentException("y value does not appear to be in correct group", "y"); + } + + return y; + } + private readonly BigInteger y; public DHPublicKeyParameters( @@ -15,10 +34,7 @@ namespace Org.BouncyCastle.Crypto.Parameters DHParameters parameters) : base(false, parameters) { - if (y == null) - throw new ArgumentNullException("y"); - - this.y = y; + this.y = Validate(y, parameters); } public DHPublicKeyParameters( @@ -27,10 +43,7 @@ namespace Org.BouncyCastle.Crypto.Parameters DerObjectIdentifier algorithmOid) : base(false, parameters, algorithmOid) { - if (y == null) - throw new ArgumentNullException("y"); - - this.y = y; + this.y = Validate(y, parameters); } public BigInteger Y -- cgit 1.4.1 From c8354a4635bc66c4878eca13b0c0ebc9da266839 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 9 Jun 2017 17:38:17 +0700 Subject: Add validation to RSA public key constructor --- crypto/src/crypto/parameters/RsaKeyParameters.cs | 24 +++++++++++++++++++++++- crypto/test/src/crypto/test/RsaTest.cs | 4 ++-- 2 files changed, 25 insertions(+), 3 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/parameters/RsaKeyParameters.cs b/crypto/src/crypto/parameters/RsaKeyParameters.cs index 72c0d806f..5480f0561 100644 --- a/crypto/src/crypto/parameters/RsaKeyParameters.cs +++ b/crypto/src/crypto/parameters/RsaKeyParameters.cs @@ -8,6 +8,26 @@ namespace Org.BouncyCastle.Crypto.Parameters public class RsaKeyParameters : AsymmetricKeyParameter { + // the value is the product of the 132 smallest primes from 3 to 751 + private static BigInteger SmallPrimesProduct = new BigInteger( + "8138E8A0FCF3A4E84A771D40FD305D7F4AA59306D7251DE54D98AF8FE95729A1" + + "F73D893FA424CD2EDC8636A6C3285E022B0E3866A565AE8108EED8591CD4FE8D" + + "2CE86165A978D719EBF647F362D33FCA29CD179FB42401CBAF3DF0C614056F9C" + + "8F3CFD51E474AFB6BC6974F78DB8ABA8E9E517FDED658591AB7502BD41849462F", + 16); + + private static BigInteger Validate(BigInteger modulus) + { + if ((modulus.IntValue & 1) == 0) + throw new ArgumentException("RSA modulus is even", "modulus"); + if (!modulus.Gcd(SmallPrimesProduct).Equals(BigInteger.One)) + throw new ArgumentException("RSA modulus has a small prime factor"); + + // TODO: add additional primePower/Composite test - expensive!! + + return modulus; + } + private readonly BigInteger modulus; private readonly BigInteger exponent; @@ -25,8 +45,10 @@ namespace Org.BouncyCastle.Crypto.Parameters throw new ArgumentException("Not a valid RSA modulus", "modulus"); if (exponent.SignValue <= 0) throw new ArgumentException("Not a valid RSA exponent", "exponent"); + if (!isPrivate && (exponent.IntValue & 1) == 0) + throw new ArgumentException("RSA publicExponent is even", "exponent"); - this.modulus = modulus; + this.modulus = Validate(modulus); this.exponent = exponent; } diff --git a/crypto/test/src/crypto/test/RsaTest.cs b/crypto/test/src/crypto/test/RsaTest.cs index d0cbedace..e3fc18d02 100644 --- a/crypto/test/src/crypto/test/RsaTest.cs +++ b/crypto/test/src/crypto/test/RsaTest.cs @@ -563,7 +563,7 @@ namespace Org.BouncyCastle.Crypto.Tests } genParam = new RsaKeyGenerationParameters( - BigInteger.ValueOf(0x11), new SecureRandom(), 16, 25); + BigInteger.ValueOf(0x11), new SecureRandom(), 128, 25); pGen.Init(genParam); for (int i = 0; i < 100; ++i) @@ -572,7 +572,7 @@ namespace Org.BouncyCastle.Crypto.Tests RsaPrivateCrtKeyParameters privKey = (RsaPrivateCrtKeyParameters) pair.Private; BigInteger pqDiff = privKey.P.Subtract(privKey.Q).Abs(); - if (pqDiff.BitLength < 5) + if (pqDiff.BitLength < 42) { Fail("P and Q too close in RSA key pair"); } -- cgit 1.4.1 From 56d5b48ee27c091a00e6aee4e6fa196634dea32b Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 9 Jun 2017 19:11:59 +0700 Subject: Port of latest encodings work from Java --- crypto/src/crypto/encodings/OaepEncoding.cs | 60 ++++++------ crypto/src/crypto/encodings/Pkcs1Encoding.cs | 132 +++++++++++++------------- crypto/test/src/crypto/test/OAEPTest.cs | 43 ++++++++- crypto/test/src/crypto/test/RSABlindedTest.cs | 8 +- crypto/test/src/crypto/test/RsaTest.cs | 93 +++++++++++++----- 5 files changed, 211 insertions(+), 125 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/encodings/OaepEncoding.cs b/crypto/src/crypto/encodings/OaepEncoding.cs index 9f5c563c2..287876f12 100644 --- a/crypto/src/crypto/encodings/OaepEncoding.cs +++ b/crypto/src/crypto/encodings/OaepEncoding.cs @@ -3,6 +3,7 @@ using System; using Org.BouncyCastle.Crypto.Digests; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Crypto.Encodings { @@ -13,7 +14,6 @@ namespace Org.BouncyCastle.Crypto.Encodings : IAsymmetricBlockCipher { private byte[] defHash; - private IDigest hash; private IDigest mgf1Hash; private IAsymmetricBlockCipher engine; @@ -48,10 +48,11 @@ namespace Org.BouncyCastle.Crypto.Encodings byte[] encodingParams) { this.engine = cipher; - this.hash = hash; this.mgf1Hash = mgf1Hash; this.defHash = new byte[hash.GetDigestSize()]; + hash.Reset(); + if (encodingParams != null) { hash.BlockUpdate(encodingParams, 0, encodingParams.Length); @@ -204,28 +205,17 @@ namespace Org.BouncyCastle.Crypto.Encodings int inLen) { byte[] data = engine.ProcessBlock(inBytes, inOff, inLen); - byte[] block; + byte[] block = new byte[engine.GetOutputBlockSize()]; // // as we may have zeros in our leading bytes for the block we produced // on encryption, we need to make sure our decrypted block comes back // the same size. // - if (data.Length < engine.GetOutputBlockSize()) - { - block = new byte[engine.GetOutputBlockSize()]; - Array.Copy(data, 0, block, block.Length - data.Length, data.Length); - } - else - { - block = data; - } + Array.Copy(data, 0, block, block.Length - data.Length, data.Length); - if (block.Length < (2 * defHash.Length) + 1) - { - throw new InvalidCipherTextException("data too short"); - } + bool shortData = (block.Length < (2 * defHash.Length) + 1); // // unmask the seed. @@ -252,36 +242,39 @@ namespace Org.BouncyCastle.Crypto.Encodings // check the hash of the encoding params. // long check to try to avoid this been a source of a timing attack. // + bool defHashWrong = false; + + for (int i = 0; i != defHash.Length; i++) { - int diff = 0; - for (int i = 0; i < defHash.Length; ++i) + if (defHash[i] != block[defHash.Length + i]) { - diff |= (byte)(defHash[i] ^ block[defHash.Length + i]); + defHashWrong = true; } - - if (diff != 0) - throw new InvalidCipherTextException("data hash wrong"); } // // find the data block // - int start; - for (start = 2 * defHash.Length; start != block.Length; start++) + int start = block.Length; + + for (int index = 2 * defHash.Length; index != block.Length; index++) { - if (block[start] != 0) + if (block[index] != 0 & start == block.Length) { - break; + start = index; } } - if (start > (block.Length - 1) || block[start] != 1) - { - throw new InvalidCipherTextException("data start wrong " + start); - } + bool dataStartWrong = (start > (block.Length - 1) | block[start] != 1); start++; + if (defHashWrong | shortData | dataStartWrong) + { + Arrays.Fill(block, 0); + throw new InvalidCipherTextException("data wrong"); + } + // // extract the data block // @@ -319,9 +312,9 @@ namespace Org.BouncyCastle.Crypto.Encodings byte[] C = new byte[4]; int counter = 0; - hash.Reset(); + mgf1Hash.Reset(); - do + while (counter < (length / hashBuf.Length)) { ItoOSP(counter, C); @@ -330,8 +323,9 @@ namespace Org.BouncyCastle.Crypto.Encodings mgf1Hash.DoFinal(hashBuf, 0); Array.Copy(hashBuf, 0, mask, counter * hashBuf.Length, hashBuf.Length); + + counter++; } - while (++counter < (length / hashBuf.Length)); if ((counter * hashBuf.Length) < length) { diff --git a/crypto/src/crypto/encodings/Pkcs1Encoding.cs b/crypto/src/crypto/encodings/Pkcs1Encoding.cs index 35fd96abe..b2d60fe4c 100644 --- a/crypto/src/crypto/encodings/Pkcs1Encoding.cs +++ b/crypto/src/crypto/encodings/Pkcs1Encoding.cs @@ -45,16 +45,18 @@ namespace Org.BouncyCastle.Crypto.Encodings } - private SecureRandom random; - private IAsymmetricBlockCipher engine; - private bool forEncryption; - private bool forPrivateKey; - private bool useStrictLength; - private int pLen = -1; - private byte[] fallback = null; + private SecureRandom random; + private IAsymmetricBlockCipher engine; + private bool forEncryption; + private bool forPrivateKey; + private bool useStrictLength; + private int pLen = -1; + private byte[] fallback = null; + private byte[] blockBuffer = null; /** * Basic constructor. + * * @param cipher */ public Pkcs1Encoding( @@ -104,9 +106,7 @@ namespace Org.BouncyCastle.Crypto.Encodings get { return engine.AlgorithmName + "/PKCS1Padding"; } } - public void Init( - bool forEncryption, - ICipherParameters parameters) + public void Init(bool forEncryption, ICipherParameters parameters) { AsymmetricKeyParameter kParam; if (parameters is ParametersWithRandom) @@ -126,6 +126,10 @@ namespace Org.BouncyCastle.Crypto.Encodings this.forPrivateKey = kParam.IsPrivate; this.forEncryption = forEncryption; + this.blockBuffer = new byte[engine.GetOutputBlockSize()]; + + if (pLen > 0 && fallback == null && random == null) + throw new ArgumentException("encoder requires random"); } public int GetInputBlockSize() @@ -255,7 +259,6 @@ namespace Org.BouncyCastle.Crypto.Encodings * @param inLen Length of the encrypted block. * @param pLen Length of the desired output. * @return The plaintext without padding, or a random value if the padding was incorrect. - * * @throws InvalidCipherTextException */ private byte[] DecodeBlockOrRandom(byte[] input, int inOff, int inLen) @@ -264,7 +267,7 @@ namespace Org.BouncyCastle.Crypto.Encodings throw new InvalidCipherTextException("sorry, this method is only for decryption, not for signing"); byte[] block = engine.ProcessBlock(input, inOff, inLen); - byte[] random = null; + byte[] random; if (this.fallback == null) { random = new byte[this.pLen]; @@ -275,37 +278,25 @@ namespace Org.BouncyCastle.Crypto.Encodings random = fallback; } - /* - * TODO: This is a potential dangerous side channel. However, you can - * fix this by changing the RSA engine in a way, that it will always - * return blocks of the same length and prepend them with 0 bytes if - * needed. - */ - if (block.Length < GetOutputBlockSize()) - throw new InvalidCipherTextException("block truncated"); + byte[] data = (useStrictLength & (block.Length != engine.GetOutputBlockSize())) ? blockBuffer : block; - /* - * TODO: Potential side channel. Fix it by making the engine always - * return blocks of the correct length. - */ - if (useStrictLength && block.Length != engine.GetOutputBlockSize()) - throw new InvalidCipherTextException("block incorrect size"); - - /* - * Check the padding. - */ - int correct = Pkcs1Encoding.CheckPkcs1Encoding(block, this.pLen); + /* + * Check the padding. + */ + int correct = CheckPkcs1Encoding(data, this.pLen); - /* - * Now, to a constant time constant memory copy of the decrypted value - * or the random value, depending on the validity of the padding. - */ + /* + * Now, to a constant time constant memory copy of the decrypted value + * or the random value, depending on the validity of the padding. + */ byte[] result = new byte[this.pLen]; for (int i = 0; i < this.pLen; i++) { - result[i] = (byte)((block[i+(block.Length-pLen)]&(~correct)) | (random[i]&correct)); + result[i] = (byte)((data[i + (data.Length - pLen)] & (~correct)) | (random[i] & correct)); } + Arrays.Fill(data, 0); + return result; } @@ -327,56 +318,67 @@ namespace Org.BouncyCastle.Crypto.Encodings } byte[] block = engine.ProcessBlock(input, inOff, inLen); + bool incorrectLength = (useStrictLength & (block.Length != engine.GetOutputBlockSize())); + byte[] data; if (block.Length < GetOutputBlockSize()) { - throw new InvalidCipherTextException("block truncated"); + data = blockBuffer; } - - byte type = block[0]; - - if (type != 1 && type != 2) + else { - throw new InvalidCipherTextException("unknown block type"); + data = block; } - if (useStrictLength && block.Length != engine.GetOutputBlockSize()) - { - throw new InvalidCipherTextException("block incorrect size"); - } + byte expectedType = (byte)(forPrivateKey ? 2 : 1); + byte type = data[0]; + + bool badType = (type != expectedType); // // find and extract the message block. // - int start; - for (start = 1; start != block.Length; start++) - { - byte pad = block[start]; + int start = FindStart(type, data); - if (pad == 0) - { - break; - } + start++; // data should start at the next byte - if (type == 1 && pad != (byte)0xff) - { - throw new InvalidCipherTextException("block padding incorrect"); - } + if (badType | (start < HeaderLength)) + { + Arrays.Fill(data, 0); + throw new InvalidCipherTextException("block incorrect"); } - start++; // data should start at the next byte - - if (start > block.Length || start < HeaderLength) + // if we get this far, it's likely to be a genuine encoding error + if (incorrectLength) { - throw new InvalidCipherTextException("no data in block"); + Arrays.Fill(data, 0); + throw new InvalidCipherTextException("block incorrect size"); } - byte[] result = new byte[block.Length - start]; + byte[] result = new byte[data.Length - start]; - Array.Copy(block, start, result, 0, result.Length); + Array.Copy(data, start, result, 0, result.Length); return result; } - } + private int FindStart(byte type, byte[] block) + { + int start = -1; + bool padErr = false; + + for (int i = 1; i != block.Length; i++) + { + byte pad = block[i]; + + if (pad == 0 & start < 0) + { + start = i; + } + padErr |= ((type == 1) & (start < 0) & (pad != (byte)0xff)); + } + + return padErr ? -1 : start; + } + } } diff --git a/crypto/test/src/crypto/test/OAEPTest.cs b/crypto/test/src/crypto/test/OAEPTest.cs index ee48a183d..bc1dd9292 100644 --- a/crypto/test/src/crypto/test/OAEPTest.cs +++ b/crypto/test/src/crypto/test/OAEPTest.cs @@ -5,7 +5,7 @@ using NUnit.Framework; using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Asn1.Pkcs; using Org.BouncyCastle.Asn1.X509; -using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; using Org.BouncyCastle.Crypto.Encodings; using Org.BouncyCastle.Crypto.Engines; using Org.BouncyCastle.Crypto.Parameters; @@ -779,6 +779,47 @@ namespace Org.BouncyCastle.Crypto.Tests OaepVecTest(1027, 4, pubParam, privParam, seed_1027_4, input_1027_4, output_1027_4); OaepVecTest(1027, 5, pubParam, privParam, seed_1027_5, input_1027_5, output_1027_5); OaepVecTest(1027, 6, pubParam, privParam, seed_1027_6, input_1027_6, output_1027_6); + + // + // OAEP - public encrypt, private decrypt differring hashes + // + IAsymmetricBlockCipher cipher = new OaepEncoding(new RsaEngine(), new Sha256Digest(), new Sha1Digest(), new byte[10]); + + cipher.Init(true, new ParametersWithRandom(pubParam, new SecureRandom())); + + byte[] input = new byte[10]; + + byte[] output = cipher.ProcessBlock(input, 0, input.Length); + + cipher.Init(false, privParam); + + output = cipher.ProcessBlock(output, 0, output.Length); + + for (int i = 0; i != input.Length; i++) + { + if (output[i] != input[i]) + { + Fail("mixed digest failed decoding"); + } + } + + cipher = new OaepEncoding(new RsaEngine(), new Sha1Digest(), new Sha256Digest(), new byte[10]); + + cipher.Init(true, new ParametersWithRandom(pubParam, new SecureRandom())); + + output = cipher.ProcessBlock(input, 0, input.Length); + + cipher.Init(false, privParam); + + output = cipher.ProcessBlock(output, 0, output.Length); + + for (int i = 0; i != input.Length; i++) + { + if (output[i] != input[i]) + { + Fail("mixed digest failed decoding"); + } + } } public static void Main( diff --git a/crypto/test/src/crypto/test/RSABlindedTest.cs b/crypto/test/src/crypto/test/RSABlindedTest.cs index 80d6e8e49..75b9f3a07 100644 --- a/crypto/test/src/crypto/test/RSABlindedTest.cs +++ b/crypto/test/src/crypto/test/RSABlindedTest.cs @@ -103,22 +103,22 @@ namespace Org.BouncyCastle.Crypto.Tests private void doTestTruncatedPkcs1Block(RsaKeyParameters pubParameters, RsaKeyParameters privParameters) { - checkForPkcs1Exception(pubParameters, privParameters, truncatedDataBlock, "block truncated"); + checkForPkcs1Exception(pubParameters, privParameters, truncatedDataBlock, "block incorrect"); } private void doTestDudPkcs1Block(RsaKeyParameters pubParameters, RsaKeyParameters privParameters) { - checkForPkcs1Exception(pubParameters, privParameters, dudBlock, "unknown block type"); + checkForPkcs1Exception(pubParameters, privParameters, dudBlock, "block incorrect"); } private void doTestWrongPaddingPkcs1Block(RsaKeyParameters pubParameters, RsaKeyParameters privParameters) { - checkForPkcs1Exception(pubParameters, privParameters, incorrectPadding, "block padding incorrect"); + checkForPkcs1Exception(pubParameters, privParameters, incorrectPadding, "block incorrect"); } private void doTestMissingDataPkcs1Block(RsaKeyParameters pubParameters, RsaKeyParameters privParameters) { - checkForPkcs1Exception(pubParameters, privParameters, missingDataBlock, "no data in block"); + checkForPkcs1Exception(pubParameters, privParameters, missingDataBlock, "block incorrect"); } private void checkForPkcs1Exception(RsaKeyParameters pubParameters, RsaKeyParameters privParameters, byte[] inputData, string expectedMessage) diff --git a/crypto/test/src/crypto/test/RsaTest.cs b/crypto/test/src/crypto/test/RsaTest.cs index e3fc18d02..e9f30cae9 100644 --- a/crypto/test/src/crypto/test/RsaTest.cs +++ b/crypto/test/src/crypto/test/RsaTest.cs @@ -54,10 +54,11 @@ namespace Org.BouncyCastle.Crypto.Tests eng.Init(true, privParameters); byte[] data = null; + byte[] overSized = null; - try - { - data = eng.ProcessBlock(oversizedSig, 0, oversizedSig.Length); + try + { + overSized = data = eng.ProcessBlock(oversizedSig, 0, oversizedSig.Length); } catch (Exception e) { @@ -70,7 +71,7 @@ namespace Org.BouncyCastle.Crypto.Tests try { - data = eng.ProcessBlock(data, 0, data.Length); + data = eng.ProcessBlock(overSized, 0, overSized.Length); Fail("oversized signature block not recognised"); } @@ -82,9 +83,22 @@ namespace Org.BouncyCastle.Crypto.Tests } } + eng = new Pkcs1Encoding(new RsaEngine(), Hex.Decode("feedbeeffeedbeeffeedbeef")); + eng.Init(false, new ParametersWithRandom(privParameters, new SecureRandom())); + + try + { + data = eng.ProcessBlock(overSized, 0, overSized.Length); + IsTrue("not fallback", Arrays.AreEqual(Hex.Decode("feedbeeffeedbeeffeedbeef"), data)); + } + catch (InvalidCipherTextException e) + { + Fail("RSA: failed - exception " + e.ToString(), e); + } - // Create the encoding with StrictLengthEnabled=false (done thru environment in Java version) - Pkcs1Encoding.StrictLengthEnabled = false; + + // Create the encoding with StrictLengthEnabled=false (done thru environment in Java version) + Pkcs1Encoding.StrictLengthEnabled = false; eng = new Pkcs1Encoding(new RsaEngine()); @@ -92,7 +106,7 @@ namespace Org.BouncyCastle.Crypto.Tests try { - data = eng.ProcessBlock(data, 0, data.Length); + data = eng.ProcessBlock(overSized, 0, overSized.Length); } catch (InvalidCipherTextException e) { @@ -104,22 +118,22 @@ namespace Org.BouncyCastle.Crypto.Tests private void doTestTruncatedPkcs1Block(RsaKeyParameters pubParameters, RsaKeyParameters privParameters) { - checkForPkcs1Exception(pubParameters, privParameters, truncatedDataBlock, "block truncated"); + checkForPkcs1Exception(pubParameters, privParameters, truncatedDataBlock, "block incorrect"); } private void doTestDudPkcs1Block(RsaKeyParameters pubParameters, RsaKeyParameters privParameters) { - checkForPkcs1Exception(pubParameters, privParameters, dudBlock, "unknown block type"); + checkForPkcs1Exception(pubParameters, privParameters, dudBlock, "block incorrect"); } private void doTestWrongPaddingPkcs1Block(RsaKeyParameters pubParameters, RsaKeyParameters privParameters) { - checkForPkcs1Exception(pubParameters, privParameters, incorrectPadding, "block padding incorrect"); + checkForPkcs1Exception(pubParameters, privParameters, incorrectPadding, "block incorrect"); } private void doTestMissingDataPkcs1Block(RsaKeyParameters pubParameters, RsaKeyParameters privParameters) { - checkForPkcs1Exception(pubParameters, privParameters, missingDataBlock, "no data in block"); + checkForPkcs1Exception(pubParameters, privParameters, missingDataBlock, "block incorrect"); } private void checkForPkcs1Exception(RsaKeyParameters pubParameters, RsaKeyParameters privParameters, byte[] inputData, string expectedMessage) @@ -431,30 +445,65 @@ namespace Org.BouncyCastle.Crypto.Tests eng.Init(false, privParameters); - try - { - data = eng.ProcessBlock(data, 0, data.Length); + byte[] plainData = null; + try + { + plainData = eng.ProcessBlock(data, 0, data.Length); } catch (Exception e) { Fail("failed - exception " + e.ToString()); } - if (!input.Equals(Hex.ToHexString(data))) - { - Fail("failed PKCS1 public/private Test"); + if (!input.Equals(Hex.ToHexString(plainData))) + { + Fail("failed PKCS1 public/private Test"); } - // - // PKCS1 - private encrypt, public decrypt - // - eng = new Pkcs1Encoding(((Pkcs1Encoding)eng).GetUnderlyingCipher()); + Pkcs1Encoding fEng = new Pkcs1Encoding(new RsaEngine(), input.Length / 2); + fEng.Init(false, new ParametersWithRandom(privParameters, new SecureRandom())); + try + { + plainData = fEng.ProcessBlock(data, 0, data.Length); + } + catch (Exception e) + { + Fail("failed - exception " + e.ToString(), e); + } + + if (!input.Equals(Hex.ToHexString(plainData))) + { + Fail("failed PKCS1 public/private fixed Test"); + } + + fEng = new Pkcs1Encoding(new RsaEngine(), input.Length); + fEng.Init(false, new ParametersWithRandom(privParameters, new SecureRandom())); + try + { + data = fEng.ProcessBlock(data, 0, data.Length); + } + catch (Exception e) + { + Fail("failed - exception " + e.ToString(), e); + } + + if (input.Equals(Hex.ToHexString(data))) + { + Fail("failed to recognise incorrect plaint text length"); + } + + data = plainData; + + // + // PKCS1 - private encrypt, public decrypt + // + eng = new Pkcs1Encoding(((Pkcs1Encoding)eng).GetUnderlyingCipher()); eng.Init(true, privParameters); try { - data = eng.ProcessBlock(data, 0, data.Length); + data = eng.ProcessBlock(plainData, 0, plainData.Length); } catch (Exception e) { -- cgit 1.4.1 From 726f9cf1b8d319aa9df17cc97104b66e7fa6a5c1 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 9 Jun 2017 19:22:34 +0700 Subject: Fix algorithm name for ChaCha7539Engine --- crypto/src/crypto/engines/ChaCha7539Engine.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/src/crypto/engines/ChaCha7539Engine.cs b/crypto/src/crypto/engines/ChaCha7539Engine.cs index 5a12be016..af4163a02 100644 --- a/crypto/src/crypto/engines/ChaCha7539Engine.cs +++ b/crypto/src/crypto/engines/ChaCha7539Engine.cs @@ -19,7 +19,7 @@ namespace Org.BouncyCastle.Crypto.Engines public override string AlgorithmName { - get { return "ChaCha" + rounds; } + get { return "ChaCha7539" + rounds; } } protected override int NonceSize -- cgit 1.4.1 From 6d6fb006877101242633b56095b011bcf0046ab3 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 9 Jun 2017 19:26:00 +0700 Subject: Write exception message to Console.Err --- crypto/test/src/crypto/examples/DESExample.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'crypto') diff --git a/crypto/test/src/crypto/examples/DESExample.cs b/crypto/test/src/crypto/examples/DESExample.cs index c026d3159..788fd643f 100644 --- a/crypto/test/src/crypto/examples/DESExample.cs +++ b/crypto/test/src/crypto/examples/DESExample.cs @@ -247,10 +247,11 @@ namespace Org.BouncyCastle.Crypto.Examples outStr.Flush(); outStr.Close(); } - catch (IOException) + catch (IOException closing) { - } - } + Console.Error.WriteLine("exception closing resources: " + closing.Message); + } + } /* * This method performs all the encryption and writes -- cgit 1.4.1 From d36b4cb85edd929b76c3c4f2ab3df31d758cfaf3 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 9 Jun 2017 19:41:15 +0700 Subject: Add PKCS OIDs for SHA512-224/256 sigs - refactor to use OID branching --- crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs | 37 +++++++++++++++------------ 1 file changed, 21 insertions(+), 16 deletions(-) (limited to 'crypto') diff --git a/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs b/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs index 042911a06..535bbbf82 100644 --- a/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs +++ b/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs @@ -9,23 +9,28 @@ namespace Org.BouncyCastle.Asn1.Pkcs // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } // public const string Pkcs1 = "1.2.840.113549.1.1"; + internal static readonly DerObjectIdentifier Pkcs1Oid = new DerObjectIdentifier(Pkcs1); + + public static readonly DerObjectIdentifier RsaEncryption = Pkcs1Oid.Branch("1"); + public static readonly DerObjectIdentifier MD2WithRsaEncryption = Pkcs1Oid.Branch("2"); + public static readonly DerObjectIdentifier MD4WithRsaEncryption = Pkcs1Oid.Branch("3"); + public static readonly DerObjectIdentifier MD5WithRsaEncryption = Pkcs1Oid.Branch("4"); + public static readonly DerObjectIdentifier Sha1WithRsaEncryption = Pkcs1Oid.Branch("5"); + public static readonly DerObjectIdentifier SrsaOaepEncryptionSet = Pkcs1Oid.Branch("6"); + public static readonly DerObjectIdentifier IdRsaesOaep = Pkcs1Oid.Branch("7"); + public static readonly DerObjectIdentifier IdMgf1 = Pkcs1Oid.Branch("8"); + public static readonly DerObjectIdentifier IdPSpecified = Pkcs1Oid.Branch("9"); + public static readonly DerObjectIdentifier IdRsassaPss = Pkcs1Oid.Branch("10"); + public static readonly DerObjectIdentifier Sha256WithRsaEncryption = Pkcs1Oid.Branch("11"); + public static readonly DerObjectIdentifier Sha384WithRsaEncryption = Pkcs1Oid.Branch("12"); + public static readonly DerObjectIdentifier Sha512WithRsaEncryption = Pkcs1Oid.Branch("13"); + public static readonly DerObjectIdentifier Sha224WithRsaEncryption = Pkcs1Oid.Branch("14"); + /** PKCS#1: 1.2.840.113549.1.1.15 */ + public static readonly DerObjectIdentifier Sha512_224WithRSAEncryption = Pkcs1Oid.Branch("15"); + /** PKCS#1: 1.2.840.113549.1.1.16 */ + public static readonly DerObjectIdentifier Sha512_256WithRSAEncryption = Pkcs1Oid.Branch("16"); - public static readonly DerObjectIdentifier RsaEncryption = new DerObjectIdentifier(Pkcs1 + ".1"); - public static readonly DerObjectIdentifier MD2WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".2"); - public static readonly DerObjectIdentifier MD4WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".3"); - public static readonly DerObjectIdentifier MD5WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".4"); - public static readonly DerObjectIdentifier Sha1WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".5"); - public static readonly DerObjectIdentifier SrsaOaepEncryptionSet = new DerObjectIdentifier(Pkcs1 + ".6"); - public static readonly DerObjectIdentifier IdRsaesOaep = new DerObjectIdentifier(Pkcs1 + ".7"); - public static readonly DerObjectIdentifier IdMgf1 = new DerObjectIdentifier(Pkcs1 + ".8"); - public static readonly DerObjectIdentifier IdPSpecified = new DerObjectIdentifier(Pkcs1 + ".9"); - public static readonly DerObjectIdentifier IdRsassaPss = new DerObjectIdentifier(Pkcs1 + ".10"); - public static readonly DerObjectIdentifier Sha256WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".11"); - public static readonly DerObjectIdentifier Sha384WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".12"); - public static readonly DerObjectIdentifier Sha512WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".13"); - public static readonly DerObjectIdentifier Sha224WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".14"); - - // + // // pkcs-3 OBJECT IDENTIFIER ::= { // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 3 } // -- cgit 1.4.1 From 60fbca299669c59edea32f393c0991e8a90df10f Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 9 Jun 2017 20:07:01 +0700 Subject: Update xmldoc --- crypto/src/asn1/Asn1Object.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'crypto') diff --git a/crypto/src/asn1/Asn1Object.cs b/crypto/src/asn1/Asn1Object.cs index a86fdbb4a..4faa81ac8 100644 --- a/crypto/src/asn1/Asn1Object.cs +++ b/crypto/src/asn1/Asn1Object.cs @@ -6,11 +6,13 @@ namespace Org.BouncyCastle.Asn1 public abstract class Asn1Object : Asn1Encodable { - /// Create a base ASN.1 object from a byte array. - /// The byte array to parse. - /// The base ASN.1 object represented by the byte array. - /// If there is a problem parsing the data. - public static Asn1Object FromByteArray( + /// Create a base ASN.1 object from a byte array. + /// The byte array to parse. + /// The base ASN.1 object represented by the byte array. + /// + /// If there is a problem parsing the data, or parsing an object did not exhaust the available data. + /// + public static Asn1Object FromByteArray( byte[] data) { try -- cgit 1.4.1 From de9a5f1debfe184c48ca76aadfebb86cf08cbdb0 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 9 Jun 2017 20:08:35 +0700 Subject: Port missing test cases from Java - Switch to newer test format --- crypto/test/src/asn1/test/MiscTest.cs | 126 ++++++++++++++++++++++++---------- 1 file changed, 90 insertions(+), 36 deletions(-) (limited to 'crypto') diff --git a/crypto/test/src/asn1/test/MiscTest.cs b/crypto/test/src/asn1/test/MiscTest.cs index 42f5dbd01..6b8411996 100644 --- a/crypto/test/src/asn1/test/MiscTest.cs +++ b/crypto/test/src/asn1/test/MiscTest.cs @@ -12,9 +12,72 @@ namespace Org.BouncyCastle.Asn1.Tests { [TestFixture] public class MiscTest - : ITest + : SimpleTest { - public ITestResult Perform() + private void DoShouldFailOnExtraData() + { + // basic construction + DerBitString s1 = new DerBitString(new byte[0], 0); + + Asn1Object.FromByteArray(s1.GetEncoded()); + + Asn1Object.FromByteArray(new BerSequence(s1).GetEncoded()); + + try + { + Asn1Object obj = Asn1Object.FromByteArray(Arrays.Concatenate(s1.GetEncoded(), new byte[1])); + Fail("no exception"); + } + catch (IOException e) + { + //if (!"Extra data detected in stream".Equals(e.Message)) + if (!"extra data found after object".Equals(e.Message)) + { + Fail("wrong exception"); + } + } + } + + private void DoDerIntegerTest() + { + try + { + new DerInteger(new byte[] { 0, 0, 0, 1}); + } + catch (ArgumentException e) + { + IsTrue("wrong exc", "malformed integer".Equals(e.Message)); + } + + try + { + new DerInteger(new byte[] {(byte)0xff, (byte)0x80, 0, 1}); + } + catch (ArgumentException e) + { + IsTrue("wrong exc", "malformed integer".Equals(e.Message)); + } + + try + { + new DerEnumerated(new byte[] { 0, 0, 0, 1}); + } + catch (ArgumentException e) + { + IsTrue("wrong exc", "malformed enumerated".Equals(e.Message)); + } + + try + { + new DerEnumerated(new byte[] {(byte)0xff, (byte)0x80, 0, 1}); + } + catch (ArgumentException e) + { + IsTrue("wrong exc", "malformed enumerated".Equals(e.Message)); + } + } + + public override void PerformTest() { byte[] testIv = { 1, 2, 3, 4, 5, 6, 7, 8 }; @@ -29,47 +92,41 @@ namespace Org.BouncyCastle.Asn1.Tests byte[] data = Base64.Decode("MA4ECAECAwQFBgcIAgIAgAMCBSAWBWhlbGxvMAoECAECAwQFBgcIFgtodHRwOi8vdGVzdA=="); - try + MemoryStream bOut = new MemoryStream(); + Asn1OutputStream aOut = new Asn1OutputStream(bOut); + + for (int i = 0; i != values.Length; i++) { - MemoryStream bOut = new MemoryStream(); - Asn1OutputStream aOut = new Asn1OutputStream(bOut); + aOut.WriteObject(values[i]); + } - for (int i = 0; i != values.Length; i++) - { - aOut.WriteObject(values[i]); - } + if (!Arrays.AreEqual(bOut.ToArray(), data)) + { + Fail("Failed data check"); + } - if (!Arrays.AreEqual(bOut.ToArray(), data)) - { - return new SimpleTestResult(false, Name + ": Failed data check"); - } + Asn1InputStream aIn = new Asn1InputStream(bOut.ToArray()); - Asn1InputStream aIn = new Asn1InputStream(bOut.ToArray()); + for (int i = 0; i != values.Length; i++) + { + Asn1Object o = aIn.ReadObject(); - for (int i = 0; i != values.Length; i++) + if (!values[i].Equals(o)) { - Asn1Object o = aIn.ReadObject(); - - if (!values[i].Equals(o)) - { - return new SimpleTestResult(false, Name + ": Failed equality test for " + o); - } - - if (o.GetHashCode() != values[i].GetHashCode()) - { - return new SimpleTestResult(false, Name + ": Failed hashCode test for " + o); - } + Fail("Failed equality test for " + o); } - return new SimpleTestResult(true, Name + ": Okay"); - } - catch (Exception e) - { - return new SimpleTestResult(false, Name + ": Failed - exception " + e.ToString(), e); + if (o.GetHashCode() != values[i].GetHashCode()) + { + Fail("Failed hashCode test for " + o); + } } + + DoShouldFailOnExtraData(); + DoDerIntegerTest(); } - public string Name + public override string Name { get { return "Misc"; } } @@ -77,10 +134,7 @@ namespace Org.BouncyCastle.Asn1.Tests public static void Main( string[] args) { - ITest test = new MiscTest(); - ITestResult result = test.Perform(); - - Console.WriteLine(result); + RunTest(new MiscTest()); } [Test] -- cgit 1.4.1 From 30ff2c5b236c329cc31aa15b6ddf9d66a4f00001 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sat, 10 Jun 2017 12:46:05 +0700 Subject: Mark RFC5114 DH groups as Obsolete --- crypto/src/crypto/agreement/DHStandardGroups.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'crypto') diff --git a/crypto/src/crypto/agreement/DHStandardGroups.cs b/crypto/src/crypto/agreement/DHStandardGroups.cs index 93b65af98..425a9784c 100644 --- a/crypto/src/crypto/agreement/DHStandardGroups.cs +++ b/crypto/src/crypto/agreement/DHStandardGroups.cs @@ -161,6 +161,11 @@ namespace Org.BouncyCastle.Crypto.Agreement + "909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28A" + "D662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24" + "855E6EEB22B3B2E5"; private static readonly string rfc5114_1024_160_q = "F518AA8781A8DF278ABA4E7D64B7CB9D49462353"; + + /// + /// Existence of a "hidden SNFS" backdoor cannot be ruled out. see https://eprint.iacr.org/2016/961.pdf . + /// + [Obsolete("Existence of a 'hidden SNFS' backdoor cannot be ruled out.")] public static readonly DHParameters rfc5114_1024_160 = FromPGQ(rfc5114_1024_160_p, rfc5114_1024_160_g, rfc5114_1024_160_q); @@ -177,6 +182,11 @@ namespace Org.BouncyCastle.Crypto.Agreement + "10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381" + "B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269" + "EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC0179" + "81BC087F2A7065B384B890D3191F2BFA"; private static readonly string rfc5114_2048_224_q = "801C0D34C58D93FE997177101F80535A4738CEBCBF389A99B36371EB"; + + /// + /// Existence of a "hidden SNFS" backdoor cannot be ruled out. see https://eprint.iacr.org/2016/961.pdf . + /// + [Obsolete("Existence of a 'hidden SNFS' backdoor cannot be ruled out.")] public static readonly DHParameters rfc5114_2048_224 = FromPGQ(rfc5114_2048_224_p, rfc5114_2048_224_g, rfc5114_2048_224_q); @@ -194,6 +204,11 @@ namespace Org.BouncyCastle.Crypto.Agreement + "184B523D1DB246C32F63078490F00EF8D647D148D4795451" + "5E2327CFEF98C582664B4C0F6CC41659"; private static readonly string rfc5114_2048_256_q = "8CF83642A709A097B447997640129DA299B1A47D1EB3750B" + "A308B0FE64F5FBD3"; + + /// + /// Existence of a "hidden SNFS" backdoor cannot be ruled out. see https://eprint.iacr.org/2016/961.pdf . + /// + [Obsolete("Existence of a 'hidden SNFS' backdoor cannot be ruled out.")] public static readonly DHParameters rfc5114_2048_256 = FromPGQ(rfc5114_2048_256_p, rfc5114_2048_256_g, rfc5114_2048_256_q); -- cgit 1.4.1 From 00b8d26b9d7de162931ae6e01e39289975501de0 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sat, 10 Jun 2017 12:58:54 +0700 Subject: Add result checks in DH agreements --- crypto/src/crypto/agreement/DHAgreement.cs | 14 ++++++++------ crypto/src/crypto/agreement/DHBasicAgreement.cs | 8 +++++--- 2 files changed, 13 insertions(+), 9 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/agreement/DHAgreement.cs b/crypto/src/crypto/agreement/DHAgreement.cs index d214caafe..b5af104f9 100644 --- a/crypto/src/crypto/agreement/DHAgreement.cs +++ b/crypto/src/crypto/agreement/DHAgreement.cs @@ -81,13 +81,15 @@ namespace Org.BouncyCastle.Crypto.Agreement throw new ArgumentNullException("message"); if (!pub.Parameters.Equals(dhParams)) - { throw new ArgumentException("Diffie-Hellman public key has wrong parameters."); - } - BigInteger p = dhParams.P; + BigInteger p = dhParams.P; - return message.ModPow(key.X, p).Multiply(pub.Y.ModPow(privateValue, p)).Mod(p); - } - } + BigInteger result = pub.Y.ModPow(privateValue, p); + if (result.Equals(BigInteger.One)) + throw new InvalidOperationException("Shared key can't be 1"); + + return message.ModPow(key.X, p).Multiply(result).Mod(p); + } + } } diff --git a/crypto/src/crypto/agreement/DHBasicAgreement.cs b/crypto/src/crypto/agreement/DHBasicAgreement.cs index 75b5e9db5..d6f017e32 100644 --- a/crypto/src/crypto/agreement/DHBasicAgreement.cs +++ b/crypto/src/crypto/agreement/DHBasicAgreement.cs @@ -54,11 +54,13 @@ namespace Org.BouncyCastle.Crypto.Agreement DHPublicKeyParameters pub = (DHPublicKeyParameters)pubKey; if (!pub.Parameters.Equals(dhParams)) - { throw new ArgumentException("Diffie-Hellman public key has wrong parameters."); - } - return pub.Y.ModPow(key.X, dhParams.P); + BigInteger result = pub.Y.ModPow(key.X, dhParams.P); + if (result.Equals(BigInteger.One)) + throw new InvalidOperationException("Shared key can't be 1"); + + return result; } } } -- cgit 1.4.1 From ff94748205290f6684a64fcccf8579b561371a56 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sat, 10 Jun 2017 14:00:03 +0700 Subject: Added s box allocation to AesEngine - mark AesFastEngine obsolete and replace all usages with AesEngine --- crypto/src/crypto/engines/AesEngine.cs | 19 ++++++++++------- crypto/src/crypto/engines/AesFastEngine.cs | 5 +++++ crypto/src/security/CipherUtilities.cs | 6 +++--- crypto/src/security/MacUtilities.cs | 2 +- crypto/src/security/WrapperUtilities.cs | 2 +- crypto/test/src/crypto/prng/test/CtrDrbgTest.cs | 26 +++++++++++------------ crypto/test/src/crypto/test/CMacTest.cs | 2 +- crypto/test/src/crypto/test/EAXTest.cs | 6 +++--- crypto/test/src/crypto/test/GCMTest.cs | 2 +- crypto/test/src/crypto/test/GMacTest.cs | 4 ++-- crypto/test/src/crypto/test/Poly1305Test.cs | 8 +++---- crypto/test/src/security/test/SecureRandomTest.cs | 4 ++-- 12 files changed, 47 insertions(+), 39 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/engines/AesEngine.cs b/crypto/src/crypto/engines/AesEngine.cs index ba62af4da..91bdf69ef 100644 --- a/crypto/src/crypto/engines/AesEngine.cs +++ b/crypto/src/crypto/engines/AesEngine.cs @@ -429,6 +429,8 @@ namespace Org.BouncyCastle.Crypto.Engines private uint C0, C1, C2, C3; private bool forEncryption; + private byte[] s; + private const int BLOCK_SIZE = 16; /** @@ -459,6 +461,7 @@ namespace Org.BouncyCastle.Crypto.Engines WorkingKey = GenerateWorkingKey(keyParameter.GetKey(), forEncryption); this.forEncryption = forEncryption; + this.s = Arrays.Clone(forEncryption ? S : Si); } public virtual string AlgorithmName @@ -560,10 +563,10 @@ namespace Org.BouncyCastle.Crypto.Engines // the final round's table is a simple function of S so we don't use a whole other four tables for it kw = KW[r]; - this.C0 = (uint)S[r0 & 255] ^ (((uint)S[(r1 >> 8) & 255]) << 8) ^ (((uint)S[(r2 >> 16) & 255]) << 16) ^ (((uint)S[(r3 >> 24) & 255]) << 24) ^ kw[0]; - this.C1 = (uint)S[r1 & 255] ^ (((uint)S[(r2 >> 8) & 255]) << 8) ^ (((uint)S[(r3 >> 16) & 255]) << 16) ^ (((uint)S[(r0 >> 24) & 255]) << 24) ^ kw[1]; - this.C2 = (uint)S[r2 & 255] ^ (((uint)S[(r3 >> 8) & 255]) << 8) ^ (((uint)S[(r0 >> 16) & 255]) << 16) ^ (((uint)S[(r1 >> 24) & 255]) << 24) ^ kw[2]; - this.C3 = (uint)S[r3 & 255] ^ (((uint)S[(r0 >> 8) & 255]) << 8) ^ (((uint)S[(r1 >> 16) & 255]) << 16) ^ (((uint)S[(r2 >> 24) & 255]) << 24) ^ kw[3]; + this.C0 = (uint)S[r0 & 255] ^ (((uint)S[(r1 >> 8) & 255]) << 8) ^ (((uint)s[(r2 >> 16) & 255]) << 16) ^ (((uint)s[(r3 >> 24) & 255]) << 24) ^ kw[0]; + this.C1 = (uint)s[r1 & 255] ^ (((uint)S[(r2 >> 8) & 255]) << 8) ^ (((uint)S[(r3 >> 16) & 255]) << 16) ^ (((uint)s[(r0 >> 24) & 255]) << 24) ^ kw[1]; + this.C2 = (uint)s[r2 & 255] ^ (((uint)S[(r3 >> 8) & 255]) << 8) ^ (((uint)S[(r0 >> 16) & 255]) << 16) ^ (((uint)S[(r1 >> 24) & 255]) << 24) ^ kw[2]; + this.C3 = (uint)s[r3 & 255] ^ (((uint)s[(r0 >> 8) & 255]) << 8) ^ (((uint)s[(r1 >> 16) & 255]) << 16) ^ (((uint)S[(r2 >> 24) & 255]) << 24) ^ kw[3]; } private void DecryptBlock(uint[][] KW) @@ -598,10 +601,10 @@ namespace Org.BouncyCastle.Crypto.Engines // the final round's table is a simple function of Si so we don't use a whole other four tables for it kw = KW[0]; - this.C0 = (uint)Si[r0 & 255] ^ (((uint)Si[(r3 >> 8) & 255]) << 8) ^ (((uint)Si[(r2 >> 16) & 255]) << 16) ^ (((uint)Si[(r1 >> 24) & 255]) << 24) ^ kw[0]; - this.C1 = (uint)Si[r1 & 255] ^ (((uint)Si[(r0 >> 8) & 255]) << 8) ^ (((uint)Si[(r3 >> 16) & 255]) << 16) ^ (((uint)Si[(r2 >> 24) & 255]) << 24) ^ kw[1]; - this.C2 = (uint)Si[r2 & 255] ^ (((uint)Si[(r1 >> 8) & 255]) << 8) ^ (((uint)Si[(r0 >> 16) & 255]) << 16) ^ (((uint)Si[(r3 >> 24) & 255]) << 24) ^ kw[2]; - this.C3 = (uint)Si[r3 & 255] ^ (((uint)Si[(r2 >> 8) & 255]) << 8) ^ (((uint)Si[(r1 >> 16) & 255]) << 16) ^ (((uint)Si[(r0 >> 24) & 255]) << 24) ^ kw[3]; + this.C0 = (uint)Si[r0 & 255] ^ (((uint)s[(r3 >> 8) & 255]) << 8) ^ (((uint)s[(r2 >> 16) & 255]) << 16) ^ (((uint)Si[(r1 >> 24) & 255]) << 24) ^ kw[0]; + this.C1 = (uint)s[r1 & 255] ^ (((uint)s[(r0 >> 8) & 255]) << 8) ^ (((uint)Si[(r3 >> 16) & 255]) << 16) ^ (((uint)s[(r2 >> 24) & 255]) << 24) ^ kw[1]; + this.C2 = (uint)s[r2 & 255] ^ (((uint)Si[(r1 >> 8) & 255]) << 8) ^ (((uint)Si[(r0 >> 16) & 255]) << 16) ^ (((uint)s[(r3 >> 24) & 255]) << 24) ^ kw[2]; + this.C3 = (uint)Si[r3 & 255] ^ (((uint)s[(r2 >> 8) & 255]) << 8) ^ (((uint)s[(r1 >> 16) & 255]) << 16) ^ (((uint)s[(r0 >> 24) & 255]) << 24) ^ kw[3]; } } } diff --git a/crypto/src/crypto/engines/AesFastEngine.cs b/crypto/src/crypto/engines/AesFastEngine.cs index 3a9c3a89e..9d3a86fd2 100644 --- a/crypto/src/crypto/engines/AesFastEngine.cs +++ b/crypto/src/crypto/engines/AesFastEngine.cs @@ -31,6 +31,11 @@ namespace Org.BouncyCastle.Crypto.Engines * This file contains the fast version with 8Kbytes of static tables for round precomputation *

*/ + /// + /// Unfortunately this class has a few side channel issues. + /// In an environment where encryption/decryption may be closely observed it should not be used. + /// + [Obsolete("Use AesEngine instead")] public class AesFastEngine : IBlockCipher { diff --git a/crypto/src/security/CipherUtilities.cs b/crypto/src/security/CipherUtilities.cs index 3217f3183..de05bc9ef 100644 --- a/crypto/src/security/CipherUtilities.cs +++ b/crypto/src/security/CipherUtilities.cs @@ -323,7 +323,7 @@ namespace Org.BouncyCastle.Security "PBEWITHMD5AND256BITAES-CBC-OPENSSL")) { return new PaddedBufferedBlockCipher( - new CbcBlockCipher(new AesFastEngine())); + new CbcBlockCipher(new AesEngine())); } } } @@ -358,7 +358,7 @@ namespace Org.BouncyCastle.Security switch (cipherAlgorithm) { case CipherAlgorithm.AES: - blockCipher = new AesFastEngine(); + blockCipher = new AesEngine(); break; case CipherAlgorithm.ARC4: streamCipher = new RC4Engine(); @@ -722,7 +722,7 @@ namespace Org.BouncyCastle.Security { switch (cipherAlgorithm) { - case CipherAlgorithm.AES: return new AesFastEngine(); + case CipherAlgorithm.AES: return new AesEngine(); case CipherAlgorithm.BLOWFISH: return new BlowfishEngine(); case CipherAlgorithm.CAMELLIA: return new CamelliaEngine(); case CipherAlgorithm.CAST5: return new Cast5Engine(); diff --git a/crypto/src/security/MacUtilities.cs b/crypto/src/security/MacUtilities.cs index fab9b1d41..278f3bec1 100644 --- a/crypto/src/security/MacUtilities.cs +++ b/crypto/src/security/MacUtilities.cs @@ -136,7 +136,7 @@ namespace Org.BouncyCastle.Security if (mechanism == "AESCMAC") { - return new CMac(new AesFastEngine()); + return new CMac(new AesEngine()); } if (mechanism == "DESMAC") { diff --git a/crypto/src/security/WrapperUtilities.cs b/crypto/src/security/WrapperUtilities.cs index ce31ea519..c57632081 100644 --- a/crypto/src/security/WrapperUtilities.cs +++ b/crypto/src/security/WrapperUtilities.cs @@ -78,7 +78,7 @@ namespace Org.BouncyCastle.Security case WrapAlgorithm.RC2WRAP: return new RC2WrapEngine(); case WrapAlgorithm.SEEDWRAP: return new SeedWrapEngine(); case WrapAlgorithm.DESEDERFC3211WRAP: return new Rfc3211WrapEngine(new DesEdeEngine()); - case WrapAlgorithm.AESRFC3211WRAP: return new Rfc3211WrapEngine(new AesFastEngine()); + case WrapAlgorithm.AESRFC3211WRAP: return new Rfc3211WrapEngine(new AesEngine()); case WrapAlgorithm.CAMELLIARFC3211WRAP: return new Rfc3211WrapEngine(new CamelliaEngine()); } } diff --git a/crypto/test/src/crypto/prng/test/CtrDrbgTest.cs b/crypto/test/src/crypto/prng/test/CtrDrbgTest.cs index 44b08f3a6..4dc09f4e8 100644 --- a/crypto/test/src/crypto/prng/test/CtrDrbgTest.cs +++ b/crypto/test/src/crypto/prng/test/CtrDrbgTest.cs @@ -149,7 +149,7 @@ namespace Org.BouncyCastle.Crypto.Prng.Test .AddAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C") .AddAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBC"), new DrbgTestVector( - new AesFastEngine(), 128, + new AesEngine(), 128, new Bit256EntropyProvider().Get(256), false, "2021222324252627", @@ -161,7 +161,7 @@ namespace Org.BouncyCastle.Crypto.Prng.Test } ), new DrbgTestVector( - new AesFastEngine(), 128, + new AesEngine(), 128, new Bit256EntropyProvider().Get(256), false, "2021222324252627", @@ -175,7 +175,7 @@ namespace Org.BouncyCastle.Crypto.Prng.Test .AddAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F") .AddAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"), new DrbgTestVector( - new AesFastEngine(), 128, + new AesEngine(), 128, new Bit256EntropyProvider().Get(256), false, "2021222324252627", @@ -188,7 +188,7 @@ namespace Org.BouncyCastle.Crypto.Prng.Test ) .SetPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F"), new DrbgTestVector( - new AesFastEngine(), 128, + new AesEngine(), 128, new Bit256EntropyProvider().Get(256), true, "2021222324252627", @@ -200,7 +200,7 @@ namespace Org.BouncyCastle.Crypto.Prng.Test } ), new DrbgTestVector( - new AesFastEngine(), 128, + new AesEngine(), 128, new Bit256EntropyProvider().Get(256), true, "2021222324252627", @@ -214,7 +214,7 @@ namespace Org.BouncyCastle.Crypto.Prng.Test .AddAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F") .AddAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"), new DrbgTestVector( - new AesFastEngine(), 128, + new AesEngine(), 128, new Bit256EntropyProvider().Get(256), true, "2021222324252627", @@ -227,7 +227,7 @@ namespace Org.BouncyCastle.Crypto.Prng.Test ) .SetPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F"), new DrbgTestVector( - new AesFastEngine(), 192, + new AesEngine(), 192, new Bit320EntropyProvider().Get(320), false, "202122232425262728292A2B", @@ -240,7 +240,7 @@ namespace Org.BouncyCastle.Crypto.Prng.Test ) .SetPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F6061626364656667"), new DrbgTestVector( - new AesFastEngine(), 192, + new AesEngine(), 192, new Bit320EntropyProvider().Get(320), true, "202122232425262728292A2B", @@ -253,7 +253,7 @@ namespace Org.BouncyCastle.Crypto.Prng.Test ) .SetPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F6061626364656667"), new DrbgTestVector( - new AesFastEngine(), 256, + new AesEngine(), 256, new Bit384EntropyProvider().Get(384), false, "202122232425262728292A2B2C2D2E2F", @@ -268,7 +268,7 @@ namespace Org.BouncyCastle.Crypto.Prng.Test .AddAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F") .AddAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"), new DrbgTestVector( - new AesFastEngine(), 256, + new AesEngine(), 256, new Bit384EntropyProvider().Get(384), true, "202122232425262728292A2B2C2D2E2F", @@ -282,7 +282,7 @@ namespace Org.BouncyCastle.Crypto.Prng.Test .AddAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F") .AddAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"), new DrbgTestVector( - new AesFastEngine(), 256, + new AesEngine(), 256, new Bit384EntropyProvider().Get(384), true, "202122232425262728292A2B2C2D2E2F", @@ -295,7 +295,7 @@ namespace Org.BouncyCastle.Crypto.Prng.Test ) .SetPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F"), new DrbgTestVector( - new AesFastEngine(), 256, + new AesEngine(), 256, new Bit384EntropyProvider().Get(384), true, "202122232425262728292A2B2C2D2E2F", @@ -310,7 +310,7 @@ namespace Org.BouncyCastle.Crypto.Prng.Test .AddAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F") .AddAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"), new DrbgTestVector( - new AesFastEngine(), 256, + new AesEngine(), 256, new Bit384EntropyProvider().Get(384), true, "202122232425262728292A2B2C2D2E2F", diff --git a/crypto/test/src/crypto/test/CMacTest.cs b/crypto/test/src/crypto/test/CMacTest.cs index d71b69f98..23ae7cb88 100644 --- a/crypto/test/src/crypto/test/CMacTest.cs +++ b/crypto/test/src/crypto/test/CMacTest.cs @@ -57,7 +57,7 @@ namespace Org.BouncyCastle.Crypto.Tests public override void PerformTest() { - IBlockCipher cipher = new AesFastEngine(); + IBlockCipher cipher = new AesEngine(); IMac mac = new CMac(cipher, 128); //128 bytes key diff --git a/crypto/test/src/crypto/test/EAXTest.cs b/crypto/test/src/crypto/test/EAXTest.cs index c6be118b2..838f26a1b 100644 --- a/crypto/test/src/crypto/test/EAXTest.cs +++ b/crypto/test/src/crypto/test/EAXTest.cs @@ -186,8 +186,8 @@ namespace Org.BouncyCastle.Crypto.Tests byte[] t, byte[] c) { - EaxBlockCipher encEax = new EaxBlockCipher(new AesFastEngine()); - EaxBlockCipher decEax = new EaxBlockCipher(new AesFastEngine()); + EaxBlockCipher encEax = new EaxBlockCipher(new AesEngine()); + EaxBlockCipher decEax = new EaxBlockCipher(new AesEngine()); AeadParameters parameters = new AeadParameters(new KeyParameter(k), macSize, n, a); encEax.Init(true, parameters); @@ -313,7 +313,7 @@ namespace Org.BouncyCastle.Crypto.Tests srng.NextBytes(datIn); srng.NextBytes(key); - AesFastEngine engine = new AesFastEngine(); + IBlockCipher engine = new AesEngine(); KeyParameter sessKey = new KeyParameter(key); EaxBlockCipher eaxCipher = new EaxBlockCipher(engine); diff --git a/crypto/test/src/crypto/test/GCMTest.cs b/crypto/test/src/crypto/test/GCMTest.cs index 943ffdad4..3f7418fb2 100644 --- a/crypto/test/src/crypto/test/GCMTest.cs +++ b/crypto/test/src/crypto/test/GCMTest.cs @@ -327,7 +327,7 @@ namespace Org.BouncyCastle.Crypto.Tests protected IBlockCipher CreateAesEngine() { - return new AesFastEngine(); + return new AesEngine(); } private void DoTestExceptions() diff --git a/crypto/test/src/crypto/test/GMacTest.cs b/crypto/test/src/crypto/test/GMacTest.cs index 383ff96b7..62088b976 100644 --- a/crypto/test/src/crypto/test/GMacTest.cs +++ b/crypto/test/src/crypto/test/GMacTest.cs @@ -107,7 +107,7 @@ namespace Org.BouncyCastle.Crypto.Tests { TestCase testCase = TEST_VECTORS[i]; - IMac mac = new GMac(new GcmBlockCipher(new AesFastEngine()), testCase.getTag().Length * 8); + IMac mac = new GMac(new GcmBlockCipher(new AesEngine()), testCase.getTag().Length * 8); ICipherParameters key = new KeyParameter(testCase.getKey()); mac.Init(new ParametersWithIV(key, testCase.getIv())); @@ -125,7 +125,7 @@ namespace Org.BouncyCastle.Crypto.Tests { try { - GMac mac = new GMac(new GcmBlockCipher(new AesFastEngine()), size); + GMac mac = new GMac(new GcmBlockCipher(new AesEngine()), size); mac.Init(new ParametersWithIV(null, new byte[16])); Fail("Expected failure for illegal mac size " + size); } diff --git a/crypto/test/src/crypto/test/Poly1305Test.cs b/crypto/test/src/crypto/test/Poly1305Test.cs index cfbff787e..7aaceb99e 100644 --- a/crypto/test/src/crypto/test/Poly1305Test.cs +++ b/crypto/test/src/crypto/test/Poly1305Test.cs @@ -129,7 +129,7 @@ namespace Org.BouncyCastle.Crypto.Tests } else { - mac = new Poly1305(new AesFastEngine()); + mac = new Poly1305(new AesEngine()); mac.Init(new ParametersWithIV(new KeyParameter(tc.key), tc.nonce)); } mac.BlockUpdate(tc.message, 0, tc.message.Length); @@ -151,7 +151,7 @@ namespace Org.BouncyCastle.Crypto.Tests byte[] output = new byte[16]; int c = 0; - IMac mac = new Poly1305(new AesFastEngine()); + IMac mac = new Poly1305(new AesEngine()); for (int loop = 0; loop < 13; loop++) { len = 0; @@ -228,7 +228,7 @@ namespace Org.BouncyCastle.Crypto.Tests byte[] output = new byte[16]; // Generate baseline - IMac poly = new Poly1305(new AesFastEngine()); + IMac poly = new Poly1305(new AesEngine()); poly.Init(new ParametersWithIV(new KeyParameter(k), new byte[16])); poly.BlockUpdate(m, 0, m.Length); @@ -274,7 +274,7 @@ namespace Org.BouncyCastle.Crypto.Tests gen.Init(new KeyGenerationParameters(new SecureRandom(), 256)); byte[] k = gen.GenerateKey(); - IMac poly = new Poly1305(new AesFastEngine()); + IMac poly = new Poly1305(new AesEngine()); poly.Init(new ParametersWithIV(new KeyParameter(k), new byte[16])); try diff --git a/crypto/test/src/security/test/SecureRandomTest.cs b/crypto/test/src/security/test/SecureRandomTest.cs index f1d83b29c..98bf75508 100644 --- a/crypto/test/src/security/test/SecureRandomTest.cs +++ b/crypto/test/src/security/test/SecureRandomTest.cs @@ -68,7 +68,7 @@ namespace Org.BouncyCastle.Security.Tests [Test] public void TestSP800Ctr() { - SecureRandom random = new SP800SecureRandomBuilder().BuildCtr(new AesFastEngine(), 256, new byte[32], false); + SecureRandom random = new SP800SecureRandomBuilder().BuildCtr(new AesEngine(), 256, new byte[32], false); CheckSecureRandom(random); } @@ -110,7 +110,7 @@ namespace Org.BouncyCastle.Security.Tests [Test] public void TestX931() { - SecureRandom random = new X931SecureRandomBuilder().Build(new AesFastEngine(), new KeyParameter(new byte[16]), false); + SecureRandom random = new X931SecureRandomBuilder().Build(new AesEngine(), new KeyParameter(new byte[16]), false); CheckSecureRandom(random); } -- cgit 1.4.1 From 4362f11288b1c5abd7c9c31b094e19e9f035ede5 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sat, 10 Jun 2017 18:30:41 +0700 Subject: Checks on DH peer public key --- crypto/src/crypto/agreement/DHAgreement.cs | 6 +- crypto/src/crypto/agreement/DHBasicAgreement.cs | 8 +- .../src/crypto/parameters/DHPublicKeyParameters.cs | 2 +- crypto/test/src/test/DHTest.cs | 93 ++++++++++++++++++++++ 4 files changed, 106 insertions(+), 3 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/agreement/DHAgreement.cs b/crypto/src/crypto/agreement/DHAgreement.cs index b5af104f9..e988c0d53 100644 --- a/crypto/src/crypto/agreement/DHAgreement.cs +++ b/crypto/src/crypto/agreement/DHAgreement.cs @@ -85,7 +85,11 @@ namespace Org.BouncyCastle.Crypto.Agreement BigInteger p = dhParams.P; - BigInteger result = pub.Y.ModPow(privateValue, p); + BigInteger peerY = pub.Y; + if (peerY == null || peerY.CompareTo(BigInteger.One) <= 0 || peerY.CompareTo(p.Subtract(BigInteger.One)) >= 0) + throw new ArgumentException("Diffie-Hellman public key is weak"); + + BigInteger result = peerY.ModPow(privateValue, p); if (result.Equals(BigInteger.One)) throw new InvalidOperationException("Shared key can't be 1"); diff --git a/crypto/src/crypto/agreement/DHBasicAgreement.cs b/crypto/src/crypto/agreement/DHBasicAgreement.cs index d6f017e32..6c3fe6595 100644 --- a/crypto/src/crypto/agreement/DHBasicAgreement.cs +++ b/crypto/src/crypto/agreement/DHBasicAgreement.cs @@ -56,7 +56,13 @@ namespace Org.BouncyCastle.Crypto.Agreement if (!pub.Parameters.Equals(dhParams)) throw new ArgumentException("Diffie-Hellman public key has wrong parameters."); - BigInteger result = pub.Y.ModPow(key.X, dhParams.P); + BigInteger p = dhParams.P; + + BigInteger peerY = pub.Y; + if (peerY == null || peerY.CompareTo(BigInteger.One) <= 0 || peerY.CompareTo(p.Subtract(BigInteger.One)) >= 0) + throw new ArgumentException("Diffie-Hellman public key is weak"); + + BigInteger result = peerY.ModPow(key.X, p); if (result.Equals(BigInteger.One)) throw new InvalidOperationException("Shared key can't be 1"); diff --git a/crypto/src/crypto/parameters/DHPublicKeyParameters.cs b/crypto/src/crypto/parameters/DHPublicKeyParameters.cs index 1704c47dc..e7aeeff19 100644 --- a/crypto/src/crypto/parameters/DHPublicKeyParameters.cs +++ b/crypto/src/crypto/parameters/DHPublicKeyParameters.cs @@ -46,7 +46,7 @@ namespace Org.BouncyCastle.Crypto.Parameters this.y = Validate(y, parameters); } - public BigInteger Y + public virtual BigInteger Y { get { return y; } } diff --git a/crypto/test/src/test/DHTest.cs b/crypto/test/src/test/DHTest.cs index 18a0d84d6..fca487008 100644 --- a/crypto/test/src/test/DHTest.cs +++ b/crypto/test/src/test/DHTest.cs @@ -633,6 +633,98 @@ namespace Org.BouncyCastle.Tests } } + internal static readonly string Message = "Hello"; + + internal static readonly SecureRandom rand = new SecureRandom(); + + public static DHParameters Ike2048() + { + BigInteger p = new BigInteger( + "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74" + + "020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f1437" + + "4fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7ed" + + "ee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf05" + + "98da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb" + + "9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3b" + + "e39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf695581718" + + "3995497cea956ae515d2261898fa051015728e5a8aacaa68ffffffffffffffff", 16); + BigInteger g = new BigInteger("2"); + return new DHParameters(p, g); + } + + internal class DHWeakPubKey + : DHPublicKeyParameters + { + private readonly BigInteger weakY; + + public DHWeakPubKey(BigInteger weakY, DHParameters parameters) + : base(BigInteger.Two, parameters) + { + this.weakY = weakY; + } + + public override BigInteger Y + { + get { return weakY; } + } + } + + /** + * Tests whether a provider accepts invalid public keys that result in predictable shared secrets. + * This test is based on RFC 2785, Section 4 and NIST SP 800-56A, + * If an attacker can modify both public keys in an ephemeral-ephemeral key agreement scheme then + * it may be possible to coerce both parties into computing the same predictable shared key. + *

+ * Note: the test is quite whimsical. If the prime p is not a safe prime then the provider itself + * cannot prevent all small-subgroup attacks because of the missing parameter q in the + * Diffie-Hellman parameters. Implementations must add additional countermeasures such as the ones + * proposed in RFC 2785. + */ + [Test] + public void TestSubgroupConfinement() + { + DHParameters parameters = Ike2048(); + BigInteger p = parameters.P, g = parameters.G; + + IAsymmetricCipherKeyPairGenerator keyGen = GeneratorUtilities.GetKeyPairGenerator("DH"); + + //keyGen.initialize(params); + keyGen.Init(new DHKeyGenerationParameters(new SecureRandom(), parameters)); + + AsymmetricCipherKeyPair kp = keyGen.GenerateKeyPair(); + AsymmetricKeyParameter priv = kp.Private; + + IBasicAgreement ka = AgreementUtilities.GetBasicAgreement("DH"); + + BigInteger[] weakPublicKeys = { BigInteger.Zero, BigInteger.One, p.Subtract(BigInteger.One), p, + p.Add(BigInteger.One), BigInteger.One.Negate() }; + + foreach (BigInteger weakKey in weakPublicKeys) + { + try + { + new DHPublicKeyParameters(weakKey, parameters); + Fail("Generated weak public key"); + } + catch (ArgumentException ex) + { + IsTrue("wrong message (constructor)", Platform.StartsWith(ex.Message, "invalid DH public key")); + } + + ka.Init(priv); + + try + { + ka.CalculateAgreement(new DHWeakPubKey(weakKey, parameters)); + Fail("Generated secrets with weak public key"); + } + catch (ArgumentException ex) + { + IsTrue("wrong message (CalculateAgreement)", "Diffie-Hellman public key is weak".Equals(ex.Message)); + } + } + } + public override void PerformTest() { TestEnc(); @@ -640,6 +732,7 @@ namespace Org.BouncyCastle.Tests TestECDH(); TestECDHC(); TestExceptions(); + TestSubgroupConfinement(); } public static void Main( -- cgit 1.4.1 From 06be229c35c4e6161f570fcdb48cd758f4e0a587 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sat, 10 Jun 2017 18:40:12 +0700 Subject: Alert when anonymous server sends CertificateRequest --- crypto/src/crypto/tls/TlsDHKeyExchange.cs | 3 +++ crypto/src/crypto/tls/TlsECDHKeyExchange.cs | 3 +++ 2 files changed, 6 insertions(+) (limited to 'crypto') diff --git a/crypto/src/crypto/tls/TlsDHKeyExchange.cs b/crypto/src/crypto/tls/TlsDHKeyExchange.cs index eec9daaca..d179068bb 100644 --- a/crypto/src/crypto/tls/TlsDHKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsDHKeyExchange.cs @@ -151,6 +151,9 @@ namespace Org.BouncyCastle.Crypto.Tls public override void ValidateCertificateRequest(CertificateRequest certificateRequest) { + if (mKeyExchange == KeyExchangeAlgorithm.DH_anon) + throw new TlsFatalAlert(AlertDescription.handshake_failure); + byte[] types = certificateRequest.CertificateTypes; for (int i = 0; i < types.Length; ++i) { diff --git a/crypto/src/crypto/tls/TlsECDHKeyExchange.cs b/crypto/src/crypto/tls/TlsECDHKeyExchange.cs index 03c162904..c508fb993 100644 --- a/crypto/src/crypto/tls/TlsECDHKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsECDHKeyExchange.cs @@ -153,6 +153,9 @@ namespace Org.BouncyCastle.Crypto.Tls public override void ValidateCertificateRequest(CertificateRequest certificateRequest) { + if (mKeyExchange == KeyExchangeAlgorithm.ECDH_anon) + throw new TlsFatalAlert(AlertDescription.handshake_failure); + /* * RFC 4492 3. [...] The ECDSA_fixed_ECDH and RSA_fixed_ECDH mechanisms are usable with * ECDH_ECDSA and ECDH_RSA. Their use with ECDHE_ECDSA and ECDHE_RSA is prohibited because -- cgit 1.4.1 From 02d523d352f37b7e1f59474dc422d8ba9bb8d5fe Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sat, 10 Jun 2017 18:43:22 +0700 Subject: Added expired certificates on CRL extension --- crypto/src/asn1/x509/X509Extensions.cs | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'crypto') diff --git a/crypto/src/asn1/x509/X509Extensions.cs b/crypto/src/asn1/x509/X509Extensions.cs index 2ef73f629..049d728bb 100644 --- a/crypto/src/asn1/x509/X509Extensions.cs +++ b/crypto/src/asn1/x509/X509Extensions.cs @@ -164,6 +164,11 @@ namespace Org.BouncyCastle.Asn1.X509 */ public static readonly DerObjectIdentifier TargetInformation = new DerObjectIdentifier("2.5.29.55"); + /** + * Expired Certificates on CRL extension + */ + public static readonly DerObjectIdentifier ExpiredCertsOnCrl = new DerObjectIdentifier("2.5.29.60"); + private readonly IDictionary extensions = Platform.CreateHashtable(); private readonly IList ordering; -- cgit 1.4.1 From a7031a60eb1ea3859f012bc34c0bae7cbcd7de54 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sat, 10 Jun 2017 19:37:28 +0700 Subject: Update GCMBlockCipher from Java API - includes basic nonce-reuse protections --- crypto/src/crypto/modes/GCMBlockCipher.cs | 70 ++++++++++++++++++++++++++++--- crypto/test/src/crypto/test/GCMTest.cs | 50 ++++++++++++++++++---- 2 files changed, 106 insertions(+), 14 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/modes/GCMBlockCipher.cs b/crypto/src/crypto/modes/GCMBlockCipher.cs index 9d940fe75..a6cd00401 100644 --- a/crypto/src/crypto/modes/GCMBlockCipher.cs +++ b/crypto/src/crypto/modes/GCMBlockCipher.cs @@ -23,7 +23,9 @@ namespace Org.BouncyCastle.Crypto.Modes // These fields are set by Init and not modified by processing private bool forEncryption; + private bool initialised; private int macSize; + private byte[] lastKey; private byte[] nonce; private byte[] initialAssociatedText; private byte[] H; @@ -90,14 +92,16 @@ namespace Org.BouncyCastle.Crypto.Modes { this.forEncryption = forEncryption; this.macBlock = null; + this.initialised = true; KeyParameter keyParam; + byte[] newNonce = null; if (parameters is AeadParameters) { AeadParameters param = (AeadParameters)parameters; - nonce = param.GetNonce(); + newNonce = param.GetNonce(); initialAssociatedText = param.GetAssociatedText(); int macSizeBits = param.MacSize; @@ -113,7 +117,7 @@ namespace Org.BouncyCastle.Crypto.Modes { ParametersWithIV param = (ParametersWithIV)parameters; - nonce = param.GetIV(); + newNonce = param.GetIV(); initialAssociatedText = null; macSize = 16; keyParam = (KeyParameter)param.Parameters; @@ -126,11 +130,32 @@ namespace Org.BouncyCastle.Crypto.Modes int bufLength = forEncryption ? BlockSize : (BlockSize + macSize); this.bufBlock = new byte[bufLength]; - if (nonce == null || nonce.Length < 1) + if (newNonce == null || newNonce.Length < 1) { throw new ArgumentException("IV must be at least 1 byte"); } + if (forEncryption) + { + if (nonce != null && Arrays.AreEqual(nonce, newNonce)) + { + if (keyParam == null) + { + throw new ArgumentException("cannot reuse nonce for GCM encryption"); + } + if (lastKey != null && Arrays.AreEqual(lastKey, keyParam.GetKey())) + { + throw new ArgumentException("cannot reuse nonce for GCM encryption"); + } + } + } + + nonce = newNonce; + if (keyParam != null) + { + lastKey = keyParam.GetKey(); + } + // TODO Restrict macSize to 16 if nonce length not 12? // Cipher always used in forward mode @@ -186,7 +211,9 @@ namespace Org.BouncyCastle.Crypto.Modes public virtual byte[] GetMac() { - return Arrays.Clone(macBlock); + return macBlock == null + ? new byte[macSize] + : Arrays.Clone(macBlock); } public virtual int GetOutputSize( @@ -219,6 +246,8 @@ namespace Org.BouncyCastle.Crypto.Modes public virtual void ProcessAadByte(byte input) { + CheckStatus(); + atBlock[atBlockPos] = input; if (++atBlockPos == BlockSize) { @@ -231,6 +260,8 @@ namespace Org.BouncyCastle.Crypto.Modes public virtual void ProcessAadBytes(byte[] inBytes, int inOff, int len) { + CheckStatus(); + for (int i = 0; i < len; ++i) { atBlock[atBlockPos] = inBytes[inOff + i]; @@ -270,6 +301,8 @@ namespace Org.BouncyCastle.Crypto.Modes byte[] output, int outOff) { + CheckStatus(); + bufBlock[bufOff] = input; if (++bufOff == bufBlock.Length) { @@ -286,6 +319,8 @@ namespace Org.BouncyCastle.Crypto.Modes byte[] output, int outOff) { + CheckStatus(); + if (input.Length < (inOff + len)) throw new DataLengthException("Input buffer too short"); @@ -325,6 +360,8 @@ namespace Org.BouncyCastle.Crypto.Modes public int DoFinal(byte[] output, int outOff) { + CheckStatus(); + if (totalLength == 0) { InitCipher(); @@ -441,6 +478,8 @@ namespace Org.BouncyCastle.Crypto.Modes { cipher.Reset(); + // note: we do not reset the nonce. + S = new byte[BlockSize]; S_at = new byte[BlockSize]; S_atPre = new byte[BlockSize]; @@ -463,9 +502,16 @@ namespace Org.BouncyCastle.Crypto.Modes macBlock = null; } - if (initialAssociatedText != null) + if (forEncryption) { - ProcessAadBytes(initialAssociatedText, 0, initialAssociatedText.Length); + initialised = false; + } + else + { + if (initialAssociatedText != null) + { + ProcessAadBytes(initialAssociatedText, 0, initialAssociatedText.Length); + } } } @@ -532,5 +578,17 @@ namespace Org.BouncyCastle.Crypto.Modes cipher.ProcessBlock(counter, 0, tmp, 0); return tmp; } + + private void CheckStatus() + { + if (!initialised) + { + if (forEncryption) + { + throw new InvalidOperationException("GCM cipher cannot be reused for encryption"); + } + throw new InvalidOperationException("GCM cipher needs to be initialised"); + } + } } } diff --git a/crypto/test/src/crypto/test/GCMTest.cs b/crypto/test/src/crypto/test/GCMTest.cs index 3f7418fb2..e5e5fc43e 100644 --- a/crypto/test/src/crypto/test/GCMTest.cs +++ b/crypto/test/src/crypto/test/GCMTest.cs @@ -357,12 +357,38 @@ namespace Org.BouncyCastle.Crypto.Tests } // TODO - //AEADTestUtil.testReset(this, new GCMBlockCipher(createAESEngine()), new GCMBlockCipher(createAESEngine()), new AEADParameters(new KeyParameter(new byte[16]), 128, new byte[16])); //AEADTestUtil.testTampering(this, gcm, new AEADParameters(new KeyParameter(new byte[16]), 128, new byte[16])); - //AEADTestUtil.testOutputSizes(this, new GCMBlockCipher(createAESEngine()), new AEADParameters(new KeyParameter( - // new byte[16]), 128, new byte[16])); - //AEADTestUtil.testBufferSizeChecks(this, new GCMBlockCipher(createAESEngine()), new AEADParameters( - // new KeyParameter(new byte[16]), 128, new byte[16])); + + //byte[] P = Strings.toByteArray("Hello world!"); + //byte[] buf = new byte[100]; + + //GCMBlockCipher c = new GCMBlockCipher(createAESEngine()); + //AEADParameters aeadParameters = new AEADParameters(new KeyParameter(new byte[16]), 128, new byte[16]); + //c.init(true, aeadParameters); + + //c.processBytes(P, 0, P.length, buf, 0); + + //c.doFinal(buf, 0); + + //try + //{ + // c.doFinal(buf, 0); + // fail("no exception on reuse"); + //} + //catch (IllegalStateException e) + //{ + // isTrue("wrong message", e.getMessage().equals("GCM cipher cannot be reused for encryption")); + //} + + //try + //{ + // c.init(true, aeadParameters); + // fail("no exception on reuse"); + //} + //catch (IllegalArgumentException e) + //{ + // isTrue("wrong message", e.getMessage().equals("cannot reuse nonce for GCM encryption")); + //} } private void RunTestCase(string[] testVector) @@ -433,13 +459,21 @@ namespace Org.BouncyCastle.Crypto.Tests GcmBlockCipher encCipher = InitCipher(encM, true, parameters); GcmBlockCipher decCipher = InitCipher(decM, false, parameters); CheckTestCase(encCipher, decCipher, testName, SA, P, C, T); + encCipher = InitCipher(encM, true, parameters); CheckTestCase(encCipher, decCipher, testName + " (reused)", SA, P, C, T); // Key reuse AeadParameters keyReuseParams = AeadTestUtilities.ReuseKey(parameters); - encCipher.Init(true, keyReuseParams); - decCipher.Init(false, keyReuseParams); - CheckTestCase(encCipher, decCipher, testName + " (key reuse)", SA, P, C, T); + + try + { + encCipher.Init(true, keyReuseParams); + Fail("no exception"); + } + catch (ArgumentException e) + { + IsTrue("wrong message", "cannot reuse nonce for GCM encryption".Equals(e.Message)); + } } private GcmBlockCipher InitCipher( -- cgit 1.4.1 From 90076c81bd0110c75678fe3c4c958dcec5d3daba Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sat, 10 Jun 2017 20:06:41 +0700 Subject: Stop decoding exceptions escaping from GetDecoderStream --- crypto/src/openpgp/PgpUtilities.cs | 81 +++++++++++++++----------- crypto/test/src/openpgp/test/PGPArmoredTest.cs | 17 ++++++ 2 files changed, 63 insertions(+), 35 deletions(-) (limited to 'crypto') diff --git a/crypto/src/openpgp/PgpUtilities.cs b/crypto/src/openpgp/PgpUtilities.cs index 055f99636..7d96dee8d 100644 --- a/crypto/src/openpgp/PgpUtilities.cs +++ b/crypto/src/openpgp/PgpUtilities.cs @@ -417,7 +417,20 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp return inputStream; } - else + + if (!IsPossiblyBase64(ch)) + { + inputStream.Position = markedPos; + + return new ArmoredInputStream(inputStream); + } + + byte[] buf = new byte[ReadAhead]; + int count = 1; + int index = 1; + + buf[0] = (byte)ch; + while (count != ReadAhead && (ch = inputStream.ReadByte()) >= 0) { if (!IsPossiblyBase64(ch)) { @@ -426,51 +439,49 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp return new ArmoredInputStream(inputStream); } - byte[] buf = new byte[ReadAhead]; - int count = 1; - int index = 1; - - buf[0] = (byte)ch; - while (count != ReadAhead && (ch = inputStream.ReadByte()) >= 0) + if (ch != '\n' && ch != '\r') { - if (!IsPossiblyBase64(ch)) - { - inputStream.Position = markedPos; + buf[index++] = (byte)ch; + } - return new ArmoredInputStream(inputStream); - } + count++; + } - if (ch != '\n' && ch != '\r') - { - buf[index++] = (byte)ch; - } + inputStream.Position = markedPos; - count++; - } + // + // nothing but new lines, little else, assume regular armoring + // + if (count < 4) + { + return new ArmoredInputStream(inputStream); + } - inputStream.Position = markedPos; + // + // test our non-blank data + // + byte[] firstBlock = new byte[8]; - // - // nothing but new lines, little else, assume regular armoring - // - if (count < 4) - { - return new ArmoredInputStream(inputStream); - } + Array.Copy(buf, 0, firstBlock, 0, firstBlock.Length); - // - // test our non-blank data - // - byte[] firstBlock = new byte[8]; - Array.Copy(buf, 0, firstBlock, 0, firstBlock.Length); - byte[] decoded = Base64.Decode(firstBlock); + try + { + byte[] decoded = Base64.Decode(firstBlock); - // + // // it's a base64 PGP block. // - bool hasHeaders = (decoded[0] & 0x80) == 0; + bool hasHeaders = (decoded[0] & 0x80) == 0; - return new ArmoredInputStream(inputStream, hasHeaders); + return new ArmoredInputStream(inputStream, hasHeaders); + } + catch (IOException e) + { + throw e; + } + catch (Exception e) + { + throw new IOException(e.Message); } } diff --git a/crypto/test/src/openpgp/test/PGPArmoredTest.cs b/crypto/test/src/openpgp/test/PGPArmoredTest.cs index aa13477ed..e48827a35 100644 --- a/crypto/test/src/openpgp/test/PGPArmoredTest.cs +++ b/crypto/test/src/openpgp/test/PGPArmoredTest.cs @@ -87,6 +87,22 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests return matches; } + private void pgpUtilTest() + { + // check decoder exception isn't escaping. + MemoryStream bIn = new MemoryStream(Strings.ToByteArray("abcde"), false); + + try + { + PgpUtilities.GetDecoderStream(bIn); + Fail("no exception"); + } + catch (IOException) + { + // expected: ignore. + } + } + private void blankLineTest() { byte[] blankLineBytes = Encoding.ASCII.GetBytes(blankLineData); @@ -241,6 +257,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests } blankLineTest(); + pgpUtilTest(); } public override string Name -- cgit 1.4.1 From c4794df16c0376050a9aff613d7b2327e9087f65 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sat, 10 Jun 2017 20:28:52 +0700 Subject: Added byte[] return when macBlock not set. --- crypto/src/crypto/modes/OCBBlockCipher.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/src/crypto/modes/OCBBlockCipher.cs b/crypto/src/crypto/modes/OCBBlockCipher.cs index e7dc466e6..91fdfff18 100644 --- a/crypto/src/crypto/modes/OCBBlockCipher.cs +++ b/crypto/src/crypto/modes/OCBBlockCipher.cs @@ -237,7 +237,9 @@ namespace Org.BouncyCastle.Crypto.Modes public virtual byte[] GetMac() { - return Arrays.Clone(macBlock); + return macBlock == null + ? new byte[macSize] + : Arrays.Clone(macBlock); } public virtual int GetOutputSize(int len) -- cgit 1.4.1 From a0fd16c00237ba5f59fb5e3fd4901f7b3c1aa97e Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sat, 10 Jun 2017 20:44:56 +0700 Subject: Misc. asn1 changes from Java API --- crypto/src/asn1/crmf/CertReqMsg.cs | 7 +++++++ crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs | 15 +++++++++++++++ crypto/src/asn1/x509/KeyPurposeId.cs | 2 ++ 3 files changed, 24 insertions(+) (limited to 'crypto') diff --git a/crypto/src/asn1/crmf/CertReqMsg.cs b/crypto/src/asn1/crmf/CertReqMsg.cs index 20fd4179a..03ce32d99 100644 --- a/crypto/src/asn1/crmf/CertReqMsg.cs +++ b/crypto/src/asn1/crmf/CertReqMsg.cs @@ -39,6 +39,13 @@ namespace Org.BouncyCastle.Asn1.Crmf return null; } + public static CertReqMsg GetInstance( + Asn1TaggedObject obj, + bool isExplicit) + { + return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit)); + } + /** * Creates a new CertReqMsg. * @param certReq CertRequest diff --git a/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs b/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs index 535bbbf82..1a9a03e9f 100644 --- a/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs +++ b/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs @@ -200,6 +200,7 @@ namespace Org.BouncyCastle.Asn1.Pkcs // rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) attributes(2)} // public const string IdAA = "1.2.840.113549.1.9.16.2"; + public static readonly DerObjectIdentifier IdAAOid = new DerObjectIdentifier(IdAA); public static readonly DerObjectIdentifier IdAAContentHint = new DerObjectIdentifier(IdAA + ".4"); // See RFC 2634 public static readonly DerObjectIdentifier IdAAMsgSigDigest = new DerObjectIdentifier(IdAA + ".5"); @@ -234,6 +235,20 @@ namespace Org.BouncyCastle.Asn1.Pkcs public static readonly DerObjectIdentifier IdAAEtsCertCrlTimestamp = new DerObjectIdentifier(IdAA + ".26"); public static readonly DerObjectIdentifier IdAAEtsArchiveTimestamp = new DerObjectIdentifier(IdAA + ".27"); + /** PKCS#9: 1.2.840.113549.1.9.16.6.2.37 - RFC 4108 */ + public static readonly DerObjectIdentifier IdAADecryptKeyID = IdAAOid.Branch("37"); + + /** PKCS#9: 1.2.840.113549.1.9.16.6.2.38 - RFC 4108 */ + public static readonly DerObjectIdentifier IdAAImplCryptoAlgs = IdAAOid.Branch("38"); + + /** PKCS#9: 1.2.840.113549.1.9.16.2.54 RFC7030*/ + public static readonly DerObjectIdentifier IdAAAsymmDecryptKeyID = IdAAOid.Branch("54"); + + /** PKCS#9: 1.2.840.113549.1.9.16.2.43 RFC7030*/ + public static readonly DerObjectIdentifier IdAAImplCompressAlgs = IdAAOid.Branch("43"); + /** PKCS#9: 1.2.840.113549.1.9.16.2.40 RFC7030*/ + public static readonly DerObjectIdentifier IdAACommunityIdentifiers = IdAAOid.Branch("40"); + [Obsolete("Use 'IdAAEtsSigPolicyID' instead")] public static readonly DerObjectIdentifier IdAASigPolicyID = IdAAEtsSigPolicyID; [Obsolete("Use 'IdAAEtsCommitmentType' instead")] diff --git a/crypto/src/asn1/x509/KeyPurposeId.cs b/crypto/src/asn1/x509/KeyPurposeId.cs index 4b48a9b51..1a564b97a 100644 --- a/crypto/src/asn1/x509/KeyPurposeId.cs +++ b/crypto/src/asn1/x509/KeyPurposeId.cs @@ -32,5 +32,7 @@ namespace Org.BouncyCastle.Asn1.X509 // microsoft key purpose ids // public static readonly KeyPurposeID IdKPSmartCardLogon = new KeyPurposeID("1.3.6.1.4.1.311.20.2.2"); + + public static readonly KeyPurposeID IdKPMacAddress = new KeyPurposeID("1.3.6.1.1.1.1.22"); } } -- cgit 1.4.1 From b8b7617bad7608602b1940fc3911b2b93c69d7f4 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sat, 10 Jun 2017 21:14:54 +0700 Subject: Update CHACHA20_POLY1305 out of draft range --- crypto/src/crypto/tls/EncryptionAlgorithm.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/tls/EncryptionAlgorithm.cs b/crypto/src/crypto/tls/EncryptionAlgorithm.cs index 96037ed20..45eef18e3 100644 --- a/crypto/src/crypto/tls/EncryptionAlgorithm.cs +++ b/crypto/src/crypto/tls/EncryptionAlgorithm.cs @@ -56,10 +56,9 @@ namespace Org.BouncyCastle.Crypto.Tls public const int CAMELLIA_256_GCM = 20; /* - * draft-ietf-tls-chacha20-poly1305-04 + * RFC 7905 */ - public const int CHACHA20_POLY1305 = 102; - [Obsolete] public const int AEAD_CHACHA20_POLY1305 = CHACHA20_POLY1305; + public const int CHACHA20_POLY1305 = 21; /* * draft-zauner-tls-aes-ocb-04 -- cgit 1.4.1 From a6593fddf3d6ddd81fd53caa4a7b983564d3ba9f Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sat, 10 Jun 2017 21:21:34 +0700 Subject: Misc. asn1 changes from Java API --- crypto/src/asn1/pkcs/CertificationRequest.cs | 3 +- crypto/src/asn1/pkcs/CertificationRequestInfo.cs | 43 +++++++++++++++--------- 2 files changed, 30 insertions(+), 16 deletions(-) (limited to 'crypto') diff --git a/crypto/src/asn1/pkcs/CertificationRequest.cs b/crypto/src/asn1/pkcs/CertificationRequest.cs index 35bdd56eb..98caa2268 100644 --- a/crypto/src/asn1/pkcs/CertificationRequest.cs +++ b/crypto/src/asn1/pkcs/CertificationRequest.cs @@ -47,7 +47,8 @@ namespace Org.BouncyCastle.Asn1.Pkcs this.sigBits = signature; } - public CertificationRequest( + [Obsolete("Use 'GetInstance' instead")] + public CertificationRequest( Asn1Sequence seq) { if (seq.Count != 3) diff --git a/crypto/src/asn1/pkcs/CertificationRequestInfo.cs b/crypto/src/asn1/pkcs/CertificationRequestInfo.cs index d57753235..6d980131e 100644 --- a/crypto/src/asn1/pkcs/CertificationRequestInfo.cs +++ b/crypto/src/asn1/pkcs/CertificationRequestInfo.cs @@ -1,7 +1,6 @@ using System; using Org.BouncyCastle.Asn1.X509; -using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Asn1.Pkcs { @@ -31,20 +30,13 @@ namespace Org.BouncyCastle.Asn1.Pkcs internal SubjectPublicKeyInfo subjectPKInfo; internal Asn1Set attributes; - public static CertificationRequestInfo GetInstance( - object obj) + public static CertificationRequestInfo GetInstance(object obj) { if (obj is CertificationRequestInfo) - { - return (CertificationRequestInfo) obj; - } - - if (obj is Asn1Sequence) - { - return new CertificationRequestInfo((Asn1Sequence) obj); - } - - throw new ArgumentException("Unknown object in factory: " + Platform.GetTypeName(obj), "obj"); + return (CertificationRequestInfo)obj; + if (obj != null) + return new CertificationRequestInfo(Asn1Sequence.GetInstance(obj)); + return null; } public CertificationRequestInfo( @@ -56,7 +48,9 @@ namespace Org.BouncyCastle.Asn1.Pkcs this.subjectPKInfo = pkInfo; this.attributes = attributes; - if (subject == null || version == null || subjectPKInfo == null) + ValidateAttributes(attributes); + + if (subject == null || version == null || subjectPKInfo == null) { throw new ArgumentException( "Not all mandatory fields set in CertificationRequestInfo generator."); @@ -81,7 +75,9 @@ namespace Org.BouncyCastle.Asn1.Pkcs attributes = Asn1Set.GetInstance(tagobj, false); } - if (subject == null || version == null || subjectPKInfo == null) + ValidateAttributes(attributes); + + if (subject == null || version == null || subjectPKInfo == null) { throw new ArgumentException( "Not all mandatory fields set in CertificationRequestInfo generator."); @@ -120,5 +116,22 @@ namespace Org.BouncyCastle.Asn1.Pkcs return new DerSequence(v); } + + private static void ValidateAttributes(Asn1Set attributes) + { + if (attributes == null) + return; + + foreach (Asn1Encodable ae in attributes) + { + Asn1Object obj = ae.ToAsn1Object(); + AttributePkcs attr = AttributePkcs.GetInstance(obj); + if (attr.AttrType.Equals(PkcsObjectIdentifiers.Pkcs9AtChallengePassword)) + { + if (attr.AttrValues.Count != 1) + throw new ArgumentException("challengePassword attribute must have one value"); + } + } + } } } -- cgit 1.4.1 From db0c88a3eae79a534ff1854089cff24fbf46c7e2 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sat, 10 Jun 2017 21:48:14 +0700 Subject: Additional fix to GOFB mode --- crypto/src/crypto/modes/GOFBBlockCipher.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/src/crypto/modes/GOFBBlockCipher.cs b/crypto/src/crypto/modes/GOFBBlockCipher.cs index 4299f11a9..436b58a1d 100644 --- a/crypto/src/crypto/modes/GOFBBlockCipher.cs +++ b/crypto/src/crypto/modes/GOFBBlockCipher.cs @@ -171,7 +171,10 @@ namespace Org.BouncyCastle.Crypto.Modes N4 += C1; if (N4 < C1) // addition is mod (2**32 - 1) { - N4++; + if (N4 > 0) + { + N4++; + } } intTobytes(N3, ofbV, 0); intTobytes(N4, ofbV, 4); -- cgit 1.4.1 From 80c81b9413658a2d68102fed6e0be1f44b5b1dd9 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sat, 10 Jun 2017 21:51:59 +0700 Subject: Add Ed25519 OID --- crypto/src/asn1/gnu/GNUObjectIdentifiers.cs | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'crypto') diff --git a/crypto/src/asn1/gnu/GNUObjectIdentifiers.cs b/crypto/src/asn1/gnu/GNUObjectIdentifiers.cs index 9311a3ac1..b322ef233 100644 --- a/crypto/src/asn1/gnu/GNUObjectIdentifiers.cs +++ b/crypto/src/asn1/gnu/GNUObjectIdentifiers.cs @@ -27,5 +27,10 @@ namespace Org.BouncyCastle.Asn1.Gnu public static readonly DerObjectIdentifier Serpent256Cfb = new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.44"); // Serpent-256-CFB public static readonly DerObjectIdentifier Crc = new DerObjectIdentifier("1.3.6.1.4.1.11591.14"); // CRC algorithms public static readonly DerObjectIdentifier Crc32 = new DerObjectIdentifier("1.3.6.1.4.1.11591.14.1"); // CRC 32 + + /** 1.3.6.1.4.1.11591.15 - ellipticCurve */ + public static readonly DerObjectIdentifier EllipticCurve = new DerObjectIdentifier("1.3.6.1.4.1.11591.15"); + + public static readonly DerObjectIdentifier Ed25519 = EllipticCurve.Branch("1"); } } -- cgit 1.4.1 From b8b3198c285952625ee00b36a809d6b8a2853a82 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sat, 10 Jun 2017 21:57:14 +0700 Subject: Add Reseed method to SP800SecureRandom --- crypto/src/crypto/prng/SP800SecureRandom.cs | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'crypto') diff --git a/crypto/src/crypto/prng/SP800SecureRandom.cs b/crypto/src/crypto/prng/SP800SecureRandom.cs index 5c5bda399..ac69e27e2 100644 --- a/crypto/src/crypto/prng/SP800SecureRandom.cs +++ b/crypto/src/crypto/prng/SP800SecureRandom.cs @@ -76,5 +76,12 @@ namespace Org.BouncyCastle.Crypto.Prng { return EntropyUtilities.GenerateSeed(mEntropySource, numBytes); } + + ///

Force a reseed of the DRBG. + /// optional additional input + public virtual void Reseed(byte[] additionalInput) + { + mDrbg.Reseed(additionalInput); + } } } -- cgit 1.4.1 From 5c185fa4dbb26af89b5cab888013f490e378ff36 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sat, 10 Jun 2017 22:09:39 +0700 Subject: Fix reset for ISO9792-2 scheme --- crypto/src/crypto/signers/Iso9796d2PssSigner.cs | 5 ++++- crypto/src/crypto/signers/Iso9796d2Signer.cs | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/src/crypto/signers/Iso9796d2PssSigner.cs b/crypto/src/crypto/signers/Iso9796d2PssSigner.cs index 3aa2e3719..6b8037095 100644 --- a/crypto/src/crypto/signers/Iso9796d2PssSigner.cs +++ b/crypto/src/crypto/signers/Iso9796d2PssSigner.cs @@ -516,6 +516,7 @@ namespace Org.BouncyCastle.Crypto.Signers if (!isOkay) { fullMessage = false; + messageLength = 0; ClearBlock(recoveredMessage); return false; } @@ -528,12 +529,14 @@ namespace Org.BouncyCastle.Crypto.Signers { if (!IsSameAs(mBuf, recoveredMessage)) { + messageLength = 0; ClearBlock(mBuf); return false; } - messageLength = 0; } + messageLength = 0; + ClearBlock(mBuf); return true; } diff --git a/crypto/src/crypto/signers/Iso9796d2Signer.cs b/crypto/src/crypto/signers/Iso9796d2Signer.cs index b90ed8f0b..303913068 100644 --- a/crypto/src/crypto/signers/Iso9796d2Signer.cs +++ b/crypto/src/crypto/signers/Iso9796d2Signer.cs @@ -360,6 +360,8 @@ namespace Org.BouncyCastle.Crypto.Signers byte[] b = cipher.ProcessBlock(block, 0, block.Length); + messageLength = 0; + ClearBlock(mBuf); ClearBlock(block); @@ -526,11 +528,15 @@ namespace Org.BouncyCastle.Crypto.Signers ClearBlock(mBuf); ClearBlock(block); + messageLength = 0; + return true; } private bool ReturnFalse(byte[] block) { + messageLength = 0; + ClearBlock(mBuf); ClearBlock(block); -- cgit 1.4.1 From 6198fad8061760809fa1e6d3ca48e96fe40f51d3 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sun, 11 Jun 2017 20:30:29 +0700 Subject: Fix race condition --- crypto/src/crypto/prng/SP800SecureRandom.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/src/crypto/prng/SP800SecureRandom.cs b/crypto/src/crypto/prng/SP800SecureRandom.cs index ac69e27e2..30c838c1b 100644 --- a/crypto/src/crypto/prng/SP800SecureRandom.cs +++ b/crypto/src/crypto/prng/SP800SecureRandom.cs @@ -81,7 +81,15 @@ namespace Org.BouncyCastle.Crypto.Prng /// optional additional input public virtual void Reseed(byte[] additionalInput) { - mDrbg.Reseed(additionalInput); + lock (this) + { + if (mDrbg == null) + { + mDrbg = mDrbgProvider.Get(mEntropySource); + } + + mDrbg.Reseed(additionalInput); + } } } } -- cgit 1.4.1 From dd37f66328b428d0ba40d059b779a5f939994326 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sun, 11 Jun 2017 21:12:44 +0700 Subject: Improve TLS exception handling --- crypto/src/crypto/tls/TlsNoCloseNotifyException.cs | 4 + crypto/src/crypto/tls/TlsProtocol.cs | 279 +++++++++++---------- crypto/src/crypto/tls/TlsServerProtocol.cs | 6 +- 3 files changed, 149 insertions(+), 140 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/tls/TlsNoCloseNotifyException.cs b/crypto/src/crypto/tls/TlsNoCloseNotifyException.cs index 72159ba47..0bafd820b 100644 --- a/crypto/src/crypto/tls/TlsNoCloseNotifyException.cs +++ b/crypto/src/crypto/tls/TlsNoCloseNotifyException.cs @@ -15,5 +15,9 @@ namespace Org.BouncyCastle.Crypto.Tls public class TlsNoCloseNotifyException : EndOfStreamException { + public TlsNoCloseNotifyException() + : base("No close_notify alert received before connection closed") + { + } } } diff --git a/crypto/src/crypto/tls/TlsProtocol.cs b/crypto/src/crypto/tls/TlsProtocol.cs index 20ea3ede6..72151d414 100644 --- a/crypto/src/crypto/tls/TlsProtocol.cs +++ b/crypto/src/crypto/tls/TlsProtocol.cs @@ -108,16 +108,95 @@ namespace Org.BouncyCastle.Crypto.Tls protected abstract TlsPeer Peer { get; } + protected virtual void HandleAlertMessage(byte alertLevel, byte alertDescription) + { + Peer.NotifyAlertReceived(alertLevel, alertDescription); + + if (alertLevel == AlertLevel.warning) + { + HandleAlertWarningMessage(alertDescription); + } + else + { + HandleFailure(); + + throw new TlsFatalAlertReceived(alertDescription); + } + } + + protected virtual void HandleAlertWarningMessage(byte alertDescription) + { + /* + * RFC 5246 7.2.1. The other party MUST respond with a close_notify alert of its own + * and close down the connection immediately, discarding any pending writes. + */ + if (alertDescription == AlertDescription.close_notify) + { + if (!mAppDataReady) + throw new TlsFatalAlert(AlertDescription.handshake_failure); + + HandleClose(false); + } + } + protected virtual void HandleChangeCipherSpecMessage() { } - protected abstract void HandleHandshakeMessage(byte type, MemoryStream buf); + protected virtual void HandleClose(bool user_canceled) + { + if (!mClosed) + { + this.mClosed = true; + + if (user_canceled && !mAppDataReady) + { + RaiseAlertWarning(AlertDescription.user_canceled, "User canceled handshake"); + } + + RaiseAlertWarning(AlertDescription.close_notify, "Connection closed"); + + mRecordStream.SafeClose(); + + if (!mAppDataReady) + { + CleanupHandshake(); + } + } + } + + protected virtual void HandleException(byte alertDescription, string message, Exception cause) + { + if (!mClosed) + { + RaiseAlertFatal(alertDescription, message, cause); + + HandleFailure(); + } + } - protected virtual void HandleWarningMessage(byte description) + protected virtual void HandleFailure() { + this.mClosed = true; + this.mFailedWithError = true; + + /* + * RFC 2246 7.2.1. The session becomes unresumable if any connection is terminated + * without proper close_notify messages with level equal to warning. + */ + // TODO This isn't quite in the right place. Also, as of TLS 1.1 the above is obsolete. + InvalidateSession(); + + mRecordStream.SafeClose(); + + if (!mAppDataReady) + { + CleanupHandshake(); + } } + protected abstract void HandleHandshakeMessage(byte type, MemoryStream buf); + protected virtual void ApplyMaxFragmentLengthExtension() { if (mSecurityParameters.maxFragmentLength >= 0) @@ -366,49 +445,11 @@ namespace Org.BouncyCastle.Crypto.Tls /* * An alert is always 2 bytes. Read the alert. */ - byte[] tmp = mAlertQueue.RemoveData(2, 0); - byte level = tmp[0]; - byte description = tmp[1]; - - Peer.NotifyAlertReceived(level, description); - - if (level == AlertLevel.fatal) - { - /* - * RFC 2246 7.2.1. The session becomes unresumable if any connection is terminated - * without proper close_notify messages with level equal to warning. - */ - InvalidateSession(); - - this.mFailedWithError = true; - this.mClosed = true; - - mRecordStream.SafeClose(); - if (!mAppDataReady) - { - CleanupHandshake(); - } - - throw new TlsFatalAlertReceived(description); - } - - /* - * RFC 5246 7.2.1. The other party MUST respond with a close_notify alert of its own - * and close down the connection immediately, discarding any pending writes. - */ - if (description == AlertDescription.close_notify) - { - if (!mAppDataReady) - { - throw new TlsFatalAlert(AlertDescription.handshake_failure); - } - HandleClose(false); - } + byte[] alert = mAlertQueue.RemoveData(2, 0); + byte alertLevel = alert[0]; + byte alertDescription = alert[1]; - /* - * If it is just a warning, we continue. - */ - HandleWarningMessage(description); + HandleAlertMessage(alertLevel, alertDescription); } } @@ -491,45 +532,55 @@ namespace Org.BouncyCastle.Crypto.Tls } catch (TlsFatalAlert e) { - this.FailWithError(AlertLevel.fatal, e.AlertDescription, "Failed to read record", e); + HandleException(e.AlertDescription, "Failed to read record", e); throw e; } - catch (Exception e) + catch (IOException e) { - this.FailWithError(AlertLevel.fatal, AlertDescription.internal_error, "Failed to read record", e); + HandleException(AlertDescription.internal_error, "Failed to read record", e); throw e; } + catch (Exception e) + { + HandleException(AlertDescription.internal_error, "Failed to read record", e); + throw new TlsFatalAlert(AlertDescription.internal_error, e); + } } protected virtual void SafeReadRecord() { try { - if (!mRecordStream.ReadRecord()) - { - if (!mAppDataReady) - { - throw new TlsFatalAlert(AlertDescription.handshake_failure); - } - throw new TlsNoCloseNotifyException(); - } + if (mRecordStream.ReadRecord()) + return; + + if (!mAppDataReady) + throw new TlsFatalAlert(AlertDescription.handshake_failure); + } + catch (TlsFatalAlertReceived e) + { + // Connection failure already handled at source + throw e; } catch (TlsFatalAlert e) { - if (!mClosed) - { - this.FailWithError(AlertLevel.fatal, e.AlertDescription, "Failed to read record", e); - } + HandleException(e.AlertDescription, "Failed to read record", e); throw e; } - catch (Exception e) + catch (IOException e) { - if (!mClosed) - { - this.FailWithError(AlertLevel.fatal, AlertDescription.internal_error, "Failed to read record", e); - } + HandleException(AlertDescription.internal_error, "Failed to read record", e); throw e; } + catch (Exception e) + { + HandleException(AlertDescription.internal_error, "Failed to read record", e); + throw new TlsFatalAlert(AlertDescription.internal_error, e); + } + + HandleFailure(); + + throw new TlsNoCloseNotifyException(); } protected virtual void SafeWriteRecord(byte type, byte[] buf, int offset, int len) @@ -540,20 +591,19 @@ namespace Org.BouncyCastle.Crypto.Tls } catch (TlsFatalAlert e) { - if (!mClosed) - { - this.FailWithError(AlertLevel.fatal, e.AlertDescription, "Failed to write record", e); - } + HandleException(e.AlertDescription, "Failed to write record", e); throw e; } - catch (Exception e) + catch (IOException e) { - if (!mClosed) - { - this.FailWithError(AlertLevel.fatal, AlertDescription.internal_error, "Failed to write record", e); - } + HandleException(AlertDescription.internal_error, "Failed to write record", e); throw e; } + catch (Exception e) + { + HandleException(AlertDescription.internal_error, "Failed to write record", e); + throw new TlsFatalAlert(AlertDescription.internal_error, e); + } } /** @@ -830,50 +880,6 @@ namespace Org.BouncyCastle.Crypto.Tls return mOutputBuffer.Read(buffer, offset, length); } - /** - * Terminate this connection with an alert. Can be used for normal closure too. - * - * @param alertLevel - * See {@link AlertLevel} for values. - * @param alertDescription - * See {@link AlertDescription} for values. - * @throws IOException - * If alert was fatal. - */ - protected virtual void FailWithError(byte alertLevel, byte alertDescription, string message, Exception cause) - { - /* - * Check if the connection is still open. - */ - if (!mClosed) - { - /* - * Prepare the message - */ - this.mClosed = true; - - if (alertLevel == AlertLevel.fatal) - { - /* - * RFC 2246 7.2.1. The session becomes unresumable if any connection is terminated - * without proper close_notify messages with level equal to warning. - */ - // TODO This isn't quite in the right place. Also, as of TLS 1.1 the above is obsolete. - InvalidateSession(); - - this.mFailedWithError = true; - } - RaiseAlert(alertLevel, alertDescription, message, cause); - mRecordStream.SafeClose(); - if (alertLevel != AlertLevel.fatal) - { - return; - } - } - - throw new IOException("TLS connection failed"); - } - protected virtual void InvalidateSession() { if (this.mSessionParameters != null) @@ -910,18 +916,29 @@ namespace Org.BouncyCastle.Crypto.Tls } } - protected virtual void RaiseAlert(byte alertLevel, byte alertDescription, string message, Exception cause) + protected virtual void RaiseAlertFatal(byte alertDescription, string message, Exception cause) { - Peer.NotifyAlertRaised(alertLevel, alertDescription, message, cause); + Peer.NotifyAlertRaised(AlertLevel.fatal, alertDescription, message, cause); - byte[] error = new byte[]{ alertLevel, alertDescription }; + byte[] alert = new byte[]{ AlertLevel.fatal, alertDescription }; - SafeWriteRecord(ContentType.alert, error, 0, 2); + try + { + mRecordStream.WriteRecord(ContentType.alert, alert, 0, 2); + } + catch (Exception) + { + // We are already processing an exception, so just ignore this + } } - protected virtual void RaiseWarning(byte alertDescription, string message) + protected virtual void RaiseAlertWarning(byte alertDescription, string message) { - RaiseAlert(AlertLevel.warning, alertDescription, message, null); + Peer.NotifyAlertRaised(AlertLevel.warning, alertDescription, message, null); + + byte[] alert = new byte[]{ AlertLevel.warning, alertDescription }; + + SafeWriteRecord(ContentType.alert, alert, 0, 2); } protected virtual void SendCertificateMessage(Certificate certificate) @@ -940,7 +957,7 @@ namespace Org.BouncyCastle.Crypto.Tls if (serverVersion.IsSsl) { string errorMessage = serverVersion.ToString() + " client didn't provide credentials"; - RaiseWarning(AlertDescription.no_certificate, errorMessage); + RaiseAlertWarning(AlertDescription.no_certificate, errorMessage); return; } } @@ -999,18 +1016,6 @@ namespace Org.BouncyCastle.Crypto.Tls HandleClose(true); } - protected virtual void HandleClose(bool user_canceled) - { - if (!mClosed) - { - if (user_canceled && !mAppDataReady) - { - RaiseWarning(AlertDescription.user_canceled, "User canceled handshake"); - } - this.FailWithError(AlertLevel.warning, AlertDescription.close_notify, "Connection closed", null); - } - } - protected internal virtual void Flush() { mRecordStream.Flush(); @@ -1046,7 +1051,7 @@ namespace Org.BouncyCastle.Crypto.Tls if (TlsUtilities.IsSsl(Context)) throw new TlsFatalAlert(AlertDescription.handshake_failure); - RaiseWarning(AlertDescription.no_renegotiation, "Renegotiation not supported"); + RaiseAlertWarning(AlertDescription.no_renegotiation, "Renegotiation not supported"); } /** diff --git a/crypto/src/crypto/tls/TlsServerProtocol.cs b/crypto/src/crypto/tls/TlsServerProtocol.cs index 298c9f42d..c2bfbcb74 100644 --- a/crypto/src/crypto/tls/TlsServerProtocol.cs +++ b/crypto/src/crypto/tls/TlsServerProtocol.cs @@ -386,11 +386,11 @@ namespace Org.BouncyCastle.Crypto.Tls } } - protected override void HandleWarningMessage(byte description) + protected override void HandleAlertWarningMessage(byte alertDescription) { - base.HandleWarningMessage(description); + base.HandleAlertWarningMessage(alertDescription); - switch (description) + switch (alertDescription) { case AlertDescription.no_certificate: { -- cgit 1.4.1 From 76e3e8a975c97f959abd6b45e9b9b94c0087f93e Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 16 Jun 2017 09:53:56 +0700 Subject: Use slightly improved addition chain for sm2p256v1 field sqrt --- .../src/math/ec/custom/gm/SM2P256V1FieldElement.cs | 42 +++++++++++----------- 1 file changed, 20 insertions(+), 22 deletions(-) (limited to 'crypto') diff --git a/crypto/src/math/ec/custom/gm/SM2P256V1FieldElement.cs b/crypto/src/math/ec/custom/gm/SM2P256V1FieldElement.cs index 669c73bd2..4f6428f9e 100644 --- a/crypto/src/math/ec/custom/gm/SM2P256V1FieldElement.cs +++ b/crypto/src/math/ec/custom/gm/SM2P256V1FieldElement.cs @@ -143,13 +143,13 @@ namespace Org.BouncyCastle.Math.EC.Custom.GM uint[] x2 = Nat256.Create(); SM2P256V1Field.Square(x1, x2); SM2P256V1Field.Multiply(x2, x1, x2); - uint[] x3 = x2; - SM2P256V1Field.Square(x2, x3); - SM2P256V1Field.Multiply(x3, x1, x3); + uint[] x4 = Nat256.Create(); + SM2P256V1Field.SquareN(x2, 2, x4); + SM2P256V1Field.Multiply(x4, x2, x4); uint[] x6 = Nat256.Create(); - SM2P256V1Field.SquareN(x3, 3, x6); - SM2P256V1Field.Multiply(x6, x3, x6); - uint[] x12 = x3; + SM2P256V1Field.SquareN(x4, 2, x6); + SM2P256V1Field.Multiply(x6, x2, x6); + uint[] x12 = x2; SM2P256V1Field.SquareN(x6, 6, x12); SM2P256V1Field.Multiply(x12, x6, x12); uint[] x24 = Nat256.Create(); @@ -162,25 +162,23 @@ namespace Org.BouncyCastle.Math.EC.Custom.GM SM2P256V1Field.Square(x30, x31); SM2P256V1Field.Multiply(x31, x1, x31); - uint[] t1 = x31; - SM2P256V1Field.Square(x31, t1); + uint[] t1 = x24; + SM2P256V1Field.SquareN(x31, 31, t1); - uint[] x32 = x12; - SM2P256V1Field.Multiply(t1, x1, x32); + uint[] x62 = x30; + SM2P256V1Field.Multiply(t1, x31, x62); SM2P256V1Field.SquareN(t1, 32, t1); - SM2P256V1Field.Multiply(t1, x32, t1); - - uint[] t2 = x24; - SM2P256V1Field.SquareN(t1, 32, t2); - SM2P256V1Field.Multiply(t2, x1, t2); - SM2P256V1Field.SquareN(t2, 32, t2); - SM2P256V1Field.Multiply(t2, t1, t2); - SM2P256V1Field.SquareN(t2, 32, t2); - SM2P256V1Field.Multiply(t2, x32, t2); - SM2P256V1Field.SquareN(t2, 32, t2); - SM2P256V1Field.Multiply(t2, x1, t2); - SM2P256V1Field.SquareN(t2, 62, t1); + SM2P256V1Field.Multiply(t1, x62, t1); + SM2P256V1Field.SquareN(t1, 62, t1); + SM2P256V1Field.Multiply(t1, x62, t1); + SM2P256V1Field.SquareN(t1, 4, t1); + SM2P256V1Field.Multiply(t1, x4, t1); + SM2P256V1Field.SquareN(t1, 32, t1); + SM2P256V1Field.Multiply(t1, x1, t1); + SM2P256V1Field.SquareN(t1, 62, t1); + + uint[] t2 = x4; SM2P256V1Field.Square(t1, t2); return Nat256.Eq(x1, t2) ? new SM2P256V1FieldElement(t1) : null; -- cgit 1.4.1 From 7b7e632102dc6e27f6183d86fd423e2be9e58696 Mon Sep 17 00:00:00 2001 From: David Hook Date: Sun, 25 Jun 2017 18:08:58 +1000 Subject: Initial cut of DSTU7564 digest and HMAC. --- crypto/src/crypto/digests/DSTU7564Digest.cs | 550 ++++++++++++++++++++++++++++ crypto/src/crypto/macs/DSTU7564Mac.cs | 156 ++++++++ crypto/test/src/crypto/test/DSTU7564Test.cs | 479 ++++++++++++++++++++++++ 3 files changed, 1185 insertions(+) create mode 100644 crypto/src/crypto/digests/DSTU7564Digest.cs create mode 100644 crypto/src/crypto/macs/DSTU7564Mac.cs create mode 100644 crypto/test/src/crypto/test/DSTU7564Test.cs (limited to 'crypto') diff --git a/crypto/src/crypto/digests/DSTU7564Digest.cs b/crypto/src/crypto/digests/DSTU7564Digest.cs new file mode 100644 index 000000000..9a785a5c9 --- /dev/null +++ b/crypto/src/crypto/digests/DSTU7564Digest.cs @@ -0,0 +1,550 @@ +using System; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Utilities; +//using Org.BouncyCastle.Utilities; + + +using Org.BouncyCastle.Utilities.Encoders; +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_; + + private ulong inputLength; + private int bufOff; + private byte[] buf; + + public Dstu7564Digest(Dstu7564Digest digest) + { + copyIn(digest); + } + + private void copyIn(Dstu7564Digest digest) + { + this.hashSize = digest.hashSize; + this.blockSize = digest.blockSize; + + this.columns = digest.columns; + this.rounds = digest.rounds; + + 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]); + } + + this.inputLength = digest.inputLength; + this.bufOff = digest.bufOff; + this.buf = Arrays.Clone(digest.buf); + } + + 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]; + } + + public string AlgorithmName + { + get { return "DSTU7564"; } + } + + + public virtual void BlockUpdate(byte[] input, int inOff, int length) + { + while (bufOff != 0 && length > 0) + { + Update(input[inOff++]); + length--; + } + + if (length > 0) + { + while (length > blockSize) + { + ProcessBlock(input, inOff); + inOff += blockSize; + inputLength += (ulong)blockSize; + length -= blockSize; + } + + while (length > 0) + { + Update(input[inOff++]); + length--; + } + } + } + + protected byte[] Pad(byte[] input, int inOff, int length) + { + //Console.WriteLine(length); + + byte[] padded; + if (blockSize - length < 13) // terminator byte + 96 bits of length + { + padded = new byte[2 * blockSize]; + } + else + { + padded = new byte[blockSize]; + } + + + 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]; + + } + + } + + P(temp1); + + Q(temp2); + + for (int i = 0; i < ROWS; ++i) + { + for (int j = 0; j < columns; ++j) + { + state_[j][i] ^= (byte)(temp1[j][i] ^ temp2[j][i]); + + } + + } + } + + public int DoFinal(byte[] output, int outOff) + { + padded_ = Pad(buf, 0, bufOff); + + ProcessBlock(padded_, 0); + + + //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); + } + + 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(); + } + + 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 bufferIndex = 0; bufferIndex < state_.Length; bufferIndex++) + { + state_[bufferIndex] = new byte[columns]; + } + + state_[0][0] = (byte)state_.Length; + + inputLength = 0; + bufOff = 0; + + Arrays.Fill(buf, (byte)0); + Arrays.Fill(padded_, (byte)0); + } + + public int GetDigestSize() + { + return hashSize; + } + + public int GetByteLength() + { + return blockSize; + } + + public void Update(byte input) + { + buf[bufOff++] = input; + if (bufOff == blockSize) + { + ProcessBlock(buf, 0); + 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() + { + return new Dstu7564Digest(this); + } + + public void Reset(IMemoable other) + { + Dstu7564Digest d = (Dstu7564Digest)other; + + 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 + } + }; + + + } +} diff --git a/crypto/src/crypto/macs/DSTU7564Mac.cs b/crypto/src/crypto/macs/DSTU7564Mac.cs new file mode 100644 index 000000000..a5f984270 --- /dev/null +++ b/crypto/src/crypto/macs/DSTU7564Mac.cs @@ -0,0 +1,156 @@ +using System; + +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Macs +{ + /// + /// Implementation of DSTU7564 mac mode + /// + public class DSTU7564Mac : IMac + { + private Dstu7564Digest engine; + private int macSize; + + private ulong inputLength; + + byte[] paddedKey; + byte[] invertedKey; + byte[] paddedInput; + + public string AlgorithmName + { + get + { + return "DSTU7564Mac"; + } + } + + public DSTU7564Mac(int macSizeBits) + { + engine = new Dstu7564Digest(macSizeBits); + macSize = macSizeBits / 8; + } + + public void Init(ICipherParameters parameters) + { + if (parameters is KeyParameter) + { + byte[] key = ((KeyParameter)parameters).GetKey(); + + invertedKey = new byte[key.Length]; + + paddedKey = PadKey(key); + + for (int byteIndex = 0; byteIndex < invertedKey.Length; byteIndex++) + { + invertedKey[byteIndex] = (byte)(key[byteIndex] ^ (byte)0xFF); + } + } + else + { + throw new ArgumentException("Bad parameter passed"); + } + + engine.BlockUpdate(paddedKey, 0, paddedKey.Length); + } + + public int GetMacSize() + { + return macSize; + } + + public void BlockUpdate(byte[] input, int inOff, int len) + { + if (input.Length - inOff < len) + { + throw new DataLengthException("Input buffer too short"); + } + + if (paddedKey == null) + { + throw new InvalidOperationException(AlgorithmName + " not initialised"); + } + + engine.BlockUpdate(input, inOff, len); + inputLength += (ulong)len; + + } + + public void Update(byte input) + { + engine.Update(input); + inputLength++; + } + + public int DoFinal(byte[] output, int outOff) + { + if (output.Length - outOff < macSize) + { + throw new DataLengthException("Output buffer too short"); + } + if (paddedKey == null) + { + throw new InvalidOperationException(AlgorithmName + " not initialised"); + } + + Pad(); + + engine.BlockUpdate(invertedKey, 0, invertedKey.Length); + + inputLength = 0; + + return engine.DoFinal(output, outOff); + } + + public void Reset() + { + inputLength = 0; + engine.Reset(); + if (paddedKey != null) + { + engine.BlockUpdate(paddedKey, 0, paddedKey.Length); + } + } + + private void Pad() + { + int extra = engine.GetByteLength() - (int)(inputLength % (ulong)engine.GetByteLength()); + if (extra < 13) // terminator byte + 96 bits of length + { + extra += engine.GetByteLength(); + } + + byte[] padded = new byte[extra]; + + padded[0] = (byte)0x80; // Defined in standard; + + // Defined in standard; + Pack.UInt64_To_LE(inputLength * 8, padded, padded.Length - 12); + + engine.BlockUpdate(padded, 0, padded.Length); + } + + private byte[] PadKey(byte[] input) + { + int paddedLen = ((input.Length + engine.GetByteLength() - 1) / engine.GetByteLength()) *engine.GetByteLength(); + + int extra = engine.GetByteLength() - (int)(input.Length % engine.GetByteLength()); + if (extra < 13) // terminator byte + 96 bits of length + { + paddedLen += engine.GetByteLength(); + } + + byte[] padded = new byte[paddedLen]; + + Array.Copy(input, 0, padded, 0, input.Length); + + padded[input.Length] = (byte)0x80; // Defined in standard; + Pack.UInt32_To_LE((uint)(input.Length * 8), padded, padded.Length - 12); // Defined in standard; + + return padded; + } + } +} diff --git a/crypto/test/src/crypto/test/DSTU7564Test.cs b/crypto/test/src/crypto/test/DSTU7564Test.cs new file mode 100644 index 000000000..d83311463 --- /dev/null +++ b/crypto/test/src/crypto/test/DSTU7564Test.cs @@ -0,0 +1,479 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * standard vector test for SHA-384 from FIPS Draft 180-2. + * + * Note, the first two vectors are _not_ from the draft, the last three are. + */ + [TestFixture] + public class Dstu7564Test + : DigestTest + { + private static string[] messages = + { + "", + "a", + "abc", + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" + }; + + private static string[] digests = + { + "cd5101d1ccdf0d1d1f4ada56e888cd724ca1a0838a3521e7131d4fb78d0f5eb6", + "c51a1d639596fb613d86557314a150c40f8fff3de48bc93a3b03c161f4105ee4", + "0bd1b36109f1318411a0517315aa46b8839df06622a278676f5487996c9cfc04", + "02621dbb53f2c7001be64d7308ecb80d21ba7797c92e98d1efc240d41e4c414b" + }; + + public Dstu7564Test() + : base(new Dstu7564Digest(256), messages, digests) + { + } + + public override void PerformTest() + { + base.PerformTest(); + + hash256Tests(); + hash384Tests(); + hash512Tests(); + macTests(); + overflowTest(); + } + + private void overflowTest() + { + int macBitSize = 256; + byte[] input = new byte[1024]; + for (int i = 0; i != input.Length; i++) + { + input[i] = (byte)(i & 0xff); + } + byte[] key = Hex.Decode("1F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100"); + + byte[] expectedMac = Hex.Decode("165382df70adcb040b17c1aced117d26d598b239ab631271a05f6d0f875ae9ea"); + byte[] mac = new byte[macBitSize / 8]; + + DSTU7564Mac dstu7564mac = new DSTU7564Mac(macBitSize); + + dstu7564mac.Init(new KeyParameter(key)); + dstu7564mac.BlockUpdate(input, 0, input.Length); + dstu7564mac.DoFinal(mac, 0); + + if (!Arrays.AreEqual(expectedMac, mac)) + { + Fail("Failed overflow test 2 - expected " + + Hex.ToHexString(expectedMac) + + " got " + Hex.ToHexString(mac)); + } + + macBitSize = 256; + input = new byte[1023]; + for (int i = 0; i != input.Length; i++) + { + input[i] = (byte)(i & 0xff); + } + key = Hex.Decode("1F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100"); + + expectedMac = Hex.Decode("ed45f163e694d990d2d835dca2f3f869a55a31396c8138161b190d5914d50686"); + mac = new byte[macBitSize / 8]; + + dstu7564mac = new DSTU7564Mac(macBitSize); + + dstu7564mac.Init(new KeyParameter(key)); + dstu7564mac.BlockUpdate(input, 0, input.Length); + dstu7564mac.DoFinal(mac, 0); + + if (!Arrays.AreEqual(expectedMac, mac)) + { + Fail("Failed overflow test 3 - expected " + + Hex.ToHexString(expectedMac) + + " got " + Hex.ToHexString(mac)); + } + + Dstu7564Digest digest = new Dstu7564Digest(macBitSize); + byte[] expectedDigest = Hex.Decode("97e84ee3b7ca2e9b0148878e88da09152952de7dd66e45d1b50ec4640932f527"); + byte[] digestBuf = new byte[macBitSize / 8]; + + digest.BlockUpdate(input, 0, input.Length); + digest.DoFinal(digestBuf, 0); + + if (!Arrays.AreEqual(expectedDigest, digestBuf)) + { + Fail("Failed overflow test 4 - expected " + + Hex.ToHexString(expectedDigest) + + " got " + Hex.ToHexString(digestBuf)); + } + + expectedDigest = Hex.Decode("6f8f0a3f8261af77581ab01cb89d4cb5ed87ca1d9954f11d5586e94b45c82fb8"); + + input = new byte[51]; + for (int i = 0; i != input.Length; i++) + { + input[i] = (byte)(i & 0xff); + } + + digest.BlockUpdate(input, 0, input.Length); + digest.DoFinal(digestBuf, 0); + + if (!Arrays.AreEqual(expectedDigest, digestBuf)) + { + Fail("Failed overflow test 5 - expected " + + Hex.ToHexString(expectedDigest) + + " got " + Hex.ToHexString(digestBuf)); + } + + input = new byte[52]; + for (int i = 0; i != input.Length; i++) + { + input[i] = (byte)(i & 0xff); + } + + expectedDigest = Hex.Decode("2d60e14ead298848031a3321ebf9e8e5263228c498e2d8ba8a857d4979aca4b3"); + + digest.BlockUpdate(input, 0, input.Length); + digest.DoFinal(digestBuf, 0); + + if (!Arrays.AreEqual(expectedDigest, digestBuf)) + { + Fail("Failed overflow test 6 - expected " + + Hex.ToHexString(expectedDigest) + + " got " + Hex.ToHexString(digestBuf)); + } + } + + 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]; + + DSTU7564Mac dstu7564mac = new DSTU7564Mac(macBitSize); + + 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)); + } + + //test 2 + macBitSize = 384; + input = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E"); + key = Hex.Decode("2F2E2D2C2B2A292827262524232221201F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100"); + + expectedMac = Hex.Decode("BEBFD8D730336F043ABACB41829E79A4D320AEDDD8D14024D5B805DA70C396FA295C281A38B30AE728A304B3F5AE490E"); + mac = new byte[macBitSize / 8]; + + dstu7564mac = new DSTU7564Mac(macBitSize); + + 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)); + } + + //test 3 + macBitSize = 512; + input = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E"); + key = Hex.Decode("3F3E3D3C3B3A393837363534333231302F2E2D2C2B2A292827262524232221201F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100"); + + expectedMac = Hex.Decode("F270043C06A5C37E65D9D791C5FBFB966E5EE709F8F54019C9A55B76CA40B70100579F269CEC24E347A9D864614CF3ABBF6610742E4DB3BD2ABC000387C49D24"); + mac = new byte[macBitSize / 8]; + + dstu7564mac = new DSTU7564Mac(macBitSize); + + 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)); + } + } + + 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)) + { + 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]; + + + 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]; + + + dstu7564 = new Dstu7564Digest(hashBitSize); + dstu7564.BlockUpdate(input, 0, input.Length); + dstu7564.DoFinal(hash, 0); + + if (!Arrays.AreEqual(expectedHash, hash)) + { + Fail("Failed hash-512 test 3 - expected " + + Hex.ToHexString(expectedHash) + + " got " + Hex.ToHexString(hash)); + } + + //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); + + if (!Arrays.AreEqual(expectedHash, hash)) + { + Fail("Failed hash-512 test 4 - 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); + + 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); + + 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)) + { + Fail("Failed hash-384 test 1 - expected " + + Hex.ToHexString(expectedHash) + + " got " + Hex.ToHexString(hash)); + } + } + + private void hash256Tests() + { + + int hashBitSize = 256; + + //test 1 + byte[] input = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F"); + byte[] expectedHash = Hex.Decode("08F4EE6F1BE6903B324C4E27990CB24EF69DD58DBE84813EE0A52F6631239875"); + 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)) + { + 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); + + 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]; + + 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)); + } + + //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); + + 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]; + + 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)); + } + + //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); + + 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) + { + return new Dstu7564Digest((Dstu7564Digest)digest); + } + + public static void Main( + string[] args) + { + RunTest(new Dstu7564Test()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + Console.WriteLine(resultText); + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} -- cgit 1.4.1 From 021e96c5f769bc44fd2c5ea54e39a07de22ea902 Mon Sep 17 00:00:00 2001 From: David Hook Date: Sun, 25 Jun 2017 18:20:32 +1000 Subject: update --- crypto/Contributors.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/Contributors.html b/crypto/Contributors.html index 5211b193f..c43b5a864 100644 --- a/crypto/Contributors.html +++ b/crypto/Contributors.html @@ -139,7 +139,10 @@

Oren Novotny (https://github.com/onovotny) - developed and maintained a fork supporting Portable Class Library, worked closely with us to integrate the changes back into the main project.

  • -

    Nicolas Dorier (https://github.com/NicolasDorier) - patch to fix culture-dependent lookups in MacUtilities. +

    Nicolas Dorier (https://github.com/NicolasDorier) - patch to fix culture-dependent lookups in MacUtilities.

    +
  • +
  • +

    Artem Storozhuk <storojs72@gmail.com> initial implementation of DSTU7564 (digest) and DSTU7624 (cipher) and their associated modes.

  • -- cgit 1.4.1 From a0b7d3b1174a6088049e360a45db4e0c1a04b32a Mon Sep 17 00:00:00 2001 From: David Hook Date: Tue, 27 Jun 2017 11:09:59 +1000 Subject: paddingfix for where pad block extends over 2 block boundary. --- crypto/src/crypto/digests/DSTU7564Digest.cs | 16 +- crypto/test/src/crypto/test/DSTU7564Test.cs | 345 ++++++++++++++++++++-------- 2 files changed, 257 insertions(+), 104 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/digests/DSTU7564Digest.cs b/crypto/src/crypto/digests/DSTU7564Digest.cs index 9a785a5c9..12057b146 100644 --- a/crypto/src/crypto/digests/DSTU7564Digest.cs +++ b/crypto/src/crypto/digests/DSTU7564Digest.cs @@ -212,12 +212,20 @@ namespace Org.BouncyCastle.Crypto.Digests { padded_ = Pad(buf, 0, bufOff); - ProcessBlock(padded_, 0); + int paddedLen = padded_.Length; + int paddedOff = 0; - - //Console.WriteLine(stateLine.Length); + while (paddedLen != 0) + { + ProcessBlock(padded_, paddedOff); + paddedOff += blockSize; + paddedLen -= blockSize; + } + + + //Console.WriteLine(stateLine.Length); - byte[][] temp = new byte[STATE_BYTE_SIZE_1024][]; + byte[][] temp = new byte[STATE_BYTE_SIZE_1024][]; for (int i = 0; i < state_.Length; i++) { temp[i] = new byte[ROWS]; diff --git a/crypto/test/src/crypto/test/DSTU7564Test.cs b/crypto/test/src/crypto/test/DSTU7564Test.cs index d83311463..f33ce9ab5 100644 --- a/crypto/test/src/crypto/test/DSTU7564Test.cs +++ b/crypto/test/src/crypto/test/DSTU7564Test.cs @@ -55,105 +55,250 @@ namespace Org.BouncyCastle.Crypto.Tests private void overflowTest() { - int macBitSize = 256; - byte[] input = new byte[1024]; - for (int i = 0; i != input.Length; i++) - { - input[i] = (byte)(i & 0xff); - } - byte[] key = Hex.Decode("1F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100"); - - byte[] expectedMac = Hex.Decode("165382df70adcb040b17c1aced117d26d598b239ab631271a05f6d0f875ae9ea"); - byte[] mac = new byte[macBitSize / 8]; - - DSTU7564Mac dstu7564mac = new DSTU7564Mac(macBitSize); - - dstu7564mac.Init(new KeyParameter(key)); - dstu7564mac.BlockUpdate(input, 0, input.Length); - dstu7564mac.DoFinal(mac, 0); - - if (!Arrays.AreEqual(expectedMac, mac)) - { - Fail("Failed overflow test 2 - expected " - + Hex.ToHexString(expectedMac) - + " got " + Hex.ToHexString(mac)); - } - - macBitSize = 256; - input = new byte[1023]; - for (int i = 0; i != input.Length; i++) - { - input[i] = (byte)(i & 0xff); - } - key = Hex.Decode("1F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100"); - - expectedMac = Hex.Decode("ed45f163e694d990d2d835dca2f3f869a55a31396c8138161b190d5914d50686"); - mac = new byte[macBitSize / 8]; - - dstu7564mac = new DSTU7564Mac(macBitSize); - - dstu7564mac.Init(new KeyParameter(key)); - dstu7564mac.BlockUpdate(input, 0, input.Length); - dstu7564mac.DoFinal(mac, 0); - - if (!Arrays.AreEqual(expectedMac, mac)) - { - Fail("Failed overflow test 3 - expected " - + Hex.ToHexString(expectedMac) - + " got " + Hex.ToHexString(mac)); - } - - Dstu7564Digest digest = new Dstu7564Digest(macBitSize); - byte[] expectedDigest = Hex.Decode("97e84ee3b7ca2e9b0148878e88da09152952de7dd66e45d1b50ec4640932f527"); - byte[] digestBuf = new byte[macBitSize / 8]; - - digest.BlockUpdate(input, 0, input.Length); - digest.DoFinal(digestBuf, 0); - - if (!Arrays.AreEqual(expectedDigest, digestBuf)) - { - Fail("Failed overflow test 4 - expected " - + Hex.ToHexString(expectedDigest) - + " got " + Hex.ToHexString(digestBuf)); - } - - expectedDigest = Hex.Decode("6f8f0a3f8261af77581ab01cb89d4cb5ed87ca1d9954f11d5586e94b45c82fb8"); - - input = new byte[51]; - for (int i = 0; i != input.Length; i++) - { - input[i] = (byte)(i & 0xff); + int macBitSize = 256; + byte[] input = new byte[1024]; + for (int i = 0; i != input.Length; i++) + { + input[i] = (byte)(i & 0xff); + } + byte[] key = Hex.Decode("1F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100"); + + byte[] expectedMac = Hex.Decode("165382df70adcb040b17c1aced117d26d598b239ab631271a05f6d0f875ae9ea"); + byte[] mac = new byte[macBitSize / 8]; + + Dstu7564Mac dstu7564mac = new Dstu7564Mac(macBitSize); + + dstu7564mac.Init(new KeyParameter(key)); + dstu7564mac.BlockUpdate(input, 0, input.Length); + dstu7564mac.DoFinal(mac, 0); + + if (!Arrays.AreEqual(expectedMac, mac)) + { + Fail("Failed overflow test 1 - expected " + + Hex.ToHexString(expectedMac) + + " got " + Hex.ToHexString(mac)); + } + + macBitSize = 256; + input = new byte[1023]; + for (int i = 0; i != input.Length; i++) + { + input[i] = (byte)(i & 0xff); + } + key = Hex.Decode("1F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100"); + + expectedMac = Hex.Decode("ed45f163e694d990d2d835dca2f3f869a55a31396c8138161b190d5914d50686"); + mac = new byte[macBitSize / 8]; + + dstu7564mac = new Dstu7564Mac(macBitSize); + + dstu7564mac.Init(new KeyParameter(key)); + dstu7564mac.BlockUpdate(input, 0, input.Length); + dstu7564mac.DoFinal(mac, 0); + + if (!Arrays.AreEqual(expectedMac, mac)) + { + Fail("Failed overflow test 2 - expected " + + Hex.ToHexString(expectedMac) + + " got " + Hex.ToHexString(mac)); + } + + Dstu7564Digest digest = new Dstu7564Digest(macBitSize); + byte[] expectedDigest = Hex.Decode("6bfc5ec8c1f5963fbed89da115d86e9330634eca341dd42fd94a7007e4af7942"); + byte[] digestBuf = new byte[macBitSize / 8]; + + digest.BlockUpdate(input, 0, input.Length); + digest.DoFinal(digestBuf, 0); + + if (!Arrays.AreEqual(expectedDigest, digestBuf)) + { + Fail("Failed overflow test 3 - expected " + + Hex.ToHexString(expectedDigest) + + " got " + Hex.ToHexString(digestBuf)); + } + + expectedDigest = Hex.Decode("6f8f0a3f8261af77581ab01cb89d4cb5ed87ca1d9954f11d5586e94b45c82fb8"); + + input = new byte[51]; + for (int i = 0; i != input.Length; i++) + { + input[i] = (byte)(i & 0xff); + } + + digest.BlockUpdate(input, 0, input.Length); + digest.DoFinal(digestBuf, 0); + + if (!Arrays.AreEqual(expectedDigest, digestBuf)) + { + Fail("Failed overflow test 4 - expected " + + Hex.ToHexString(expectedDigest) + + " got " + Hex.ToHexString(digestBuf)); + } + + input = new byte[52]; + for (int i = 0; i != input.Length; i++) + { + input[i] = (byte)(i & 0xff); + } + + expectedDigest = Hex.Decode("8b6fe2ba77e684b2a1ac82232f4efc49f681cd18c82a0cfff530186a2fc642d2"); + + digest.BlockUpdate(input, 0, input.Length); + digest.DoFinal(digestBuf, 0); + + if (!Arrays.AreEqual(expectedDigest, digestBuf)) + { + Fail("Failed overflow test 5 - expected " + + Hex.ToHexString(expectedDigest) + + " got " + Hex.ToHexString(digestBuf)); + } + + + input = new byte[53]; + for (int i = 0; i != input.Length; i++) + { + input[i] = (byte)(i & 0xff); + } + + expectedDigest = Hex.Decode("837f2b0cbe39a4defdfcb44272288d4091cab850161c70695d7831fc5f00e171"); + + digest.BlockUpdate(input, 0, input.Length); + digest.DoFinal(digestBuf, 0); + + if (!Arrays.AreEqual(expectedDigest, digestBuf)) + { + Fail("Failed overflow test 6 - expected " + + Hex.ToHexString(expectedDigest) + + " got " + Hex.ToHexString(digestBuf)); + } + + input = new byte[54]; + for (int i = 0; i != input.Length; i++) + { + input[i] = (byte)(i & 0xff); + } + + expectedDigest = Hex.Decode("21d423d5b8c7f18a0da42cdd95b36b66344125e2adc6edeab5899926442113bc"); + + digest.BlockUpdate(input, 0, input.Length); + digest.DoFinal(digestBuf, 0); + + if (!Arrays.AreEqual(expectedDigest, digestBuf)) + { + Fail("Failed overflow test 7 - expected " + + Hex.ToHexString(expectedDigest) + + " got " + Hex.ToHexString(digestBuf)); + } + + input = new byte[55]; + for (int i = 0; i != input.Length; i++) + { + input[i] = (byte)(i & 0xff); + } + + expectedDigest = Hex.Decode("0e7bf74464b81b3ae7d904170776d29f4b02a7227da578dd562d01027af7fd0e"); + + digest.BlockUpdate(input, 0, input.Length); + digest.DoFinal(digestBuf, 0); + + if (!Arrays.AreEqual(expectedDigest, digestBuf)) + { + Fail("Failed overflow test 8 - expected " + + Hex.ToHexString(expectedDigest) + + " got " + Hex.ToHexString(digestBuf)); + } + + input = new byte[56]; + for (int i = 0; i != input.Length; i++) + { + input[i] = (byte)(i & 0xff); + } + + expectedDigest = Hex.Decode("badea1f49cbcec94acec52b4c695acdddd786cca5a6763929f341a58c5134b3b"); + + digest.BlockUpdate(input, 0, input.Length); + digest.DoFinal(digestBuf, 0); + + if (!Arrays.AreEqual(expectedDigest, digestBuf)) + { + Fail("Failed overflow test 9 - expected " + + Hex.ToHexString(expectedDigest) + + " got " + Hex.ToHexString(digestBuf)); + } + + input = new byte[57]; + for (int i = 0; i != input.Length; i++) + { + input[i] = (byte)(i & 0xff); + } + + expectedDigest = Hex.Decode("a13b5f6f53ee043292ed65b66c1d49759be4d2fe0c2f6148f2416487965f7bde"); + + digest.BlockUpdate(input, 0, input.Length); + digest.DoFinal(digestBuf, 0); + + if (!Arrays.AreEqual(expectedDigest, digestBuf)) + { + Fail("Failed overflow test 10 - expected " + + Hex.ToHexString(expectedDigest) + + " got " + Hex.ToHexString(digestBuf)); + } + + input = new byte[63]; + for (int i = 0; i != input.Length; i++) + { + input[i] = (byte)(i & 0xff); + } + + expectedDigest = Hex.Decode("03a44a02c9ffafb43addb290bbcf3b8168f624e8cbd332dc6a9dc7df9d39cbc2"); + + digest.BlockUpdate(input, 0, input.Length); + digest.DoFinal(digestBuf, 0); + + if (!Arrays.AreEqual(expectedDigest, digestBuf)) + { + Fail("Failed overflow test 11 - expected " + + Hex.ToHexString(expectedDigest) + + " got " + Hex.ToHexString(digestBuf)); + } + + input = new byte[64]; + for (int i = 0; i != input.Length; i++) + { + input[i] = (byte)(i & 0xff); + } + + expectedDigest = Hex.Decode("08f4ee6f1be6903b324c4e27990cb24ef69dd58dbe84813ee0a52f6631239875"); + + digest.BlockUpdate(input, 0, input.Length); + digest.DoFinal(digestBuf, 0); + + if (!Arrays.AreEqual(expectedDigest, digestBuf)) + { + Fail("Failed overflow test 12 - expected " + + Hex.ToHexString(expectedDigest) + + " got " + Hex.ToHexString(digestBuf)); + } + + input = new byte[65]; + for (int i = 0; i != input.Length; i++) + { + input[i] = (byte)(i & 0xff); + } + + expectedDigest = Hex.Decode("a81c2fb92351f370050b7c36cd51736d5603a50ec1106cbd5fe1c9be2e5c77a6"); + + digest.BlockUpdate(input, 0, input.Length); + digest.DoFinal(digestBuf, 0); + + if (!Arrays.AreEqual(expectedDigest, digestBuf)) + { + Fail("Failed overflow test 13 - expected " + + Hex.ToHexString(expectedDigest) + + " got " + Hex.ToHexString(digestBuf)); + } } - digest.BlockUpdate(input, 0, input.Length); - digest.DoFinal(digestBuf, 0); - - if (!Arrays.AreEqual(expectedDigest, digestBuf)) - { - Fail("Failed overflow test 5 - expected " - + Hex.ToHexString(expectedDigest) - + " got " + Hex.ToHexString(digestBuf)); - } - - input = new byte[52]; - for (int i = 0; i != input.Length; i++) - { - input[i] = (byte)(i & 0xff); - } - - expectedDigest = Hex.Decode("2d60e14ead298848031a3321ebf9e8e5263228c498e2d8ba8a857d4979aca4b3"); - - digest.BlockUpdate(input, 0, input.Length); - digest.DoFinal(digestBuf, 0); - - if (!Arrays.AreEqual(expectedDigest, digestBuf)) - { - Fail("Failed overflow test 6 - expected " - + Hex.ToHexString(expectedDigest) - + " got " + Hex.ToHexString(digestBuf)); - } - } - private void macTests() { @@ -165,7 +310,7 @@ namespace Org.BouncyCastle.Crypto.Tests 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); @@ -186,7 +331,7 @@ namespace Org.BouncyCastle.Crypto.Tests 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); @@ -207,7 +352,7 @@ namespace Org.BouncyCastle.Crypto.Tests 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); -- cgit 1.4.1 From d09b1726efd194b28fba15a9833170d7077abe23 Mon Sep 17 00:00:00 2001 From: David Hook Date: Thu, 6 Jul 2017 10:38:34 +1000 Subject: added missing null check --- crypto/src/crypto/digests/DSTU7564Digest.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/src/crypto/digests/DSTU7564Digest.cs b/crypto/src/crypto/digests/DSTU7564Digest.cs index 12057b146..9de41dd6b 100644 --- a/crypto/src/crypto/digests/DSTU7564Digest.cs +++ b/crypto/src/crypto/digests/DSTU7564Digest.cs @@ -282,7 +282,11 @@ namespace Org.BouncyCastle.Crypto.Digests bufOff = 0; Arrays.Fill(buf, (byte)0); - Arrays.Fill(padded_, (byte)0); + + if (padded_ != null) + { + Arrays.Fill(padded_, (byte)0); + } } public int GetDigestSize() -- cgit 1.4.1 From 96da0eba42bdf27548bbd391237f71905dd5b898 Mon Sep 17 00:00:00 2001 From: David Hook Date: Thu, 6 Jul 2017 11:00:16 +1000 Subject: fixed case of definition --- crypto/src/crypto/macs/DSTU7564Mac.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/macs/DSTU7564Mac.cs b/crypto/src/crypto/macs/DSTU7564Mac.cs index a5f984270..907355487 100644 --- a/crypto/src/crypto/macs/DSTU7564Mac.cs +++ b/crypto/src/crypto/macs/DSTU7564Mac.cs @@ -9,7 +9,7 @@ namespace Org.BouncyCastle.Crypto.Macs /// /// Implementation of DSTU7564 mac mode /// - public class DSTU7564Mac : IMac + public class Dstu7564Mac : IMac { private Dstu7564Digest engine; private int macSize; @@ -28,7 +28,7 @@ namespace Org.BouncyCastle.Crypto.Macs } } - public DSTU7564Mac(int macSizeBits) + public Dstu7564Mac(int macSizeBits) { engine = new Dstu7564Digest(macSizeBits); macSize = macSizeBits / 8; -- cgit 1.4.1 From 346ea3d9458930686f6fc9a213227091e25658ae Mon Sep 17 00:00:00 2001 From: David Hook Date: Thu, 6 Jul 2017 11:29:47 +1000 Subject: added extra vector --- crypto/test/src/crypto/test/DSTU7564Test.cs | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) (limited to 'crypto') diff --git a/crypto/test/src/crypto/test/DSTU7564Test.cs b/crypto/test/src/crypto/test/DSTU7564Test.cs index f33ce9ab5..98f0bbdea 100644 --- a/crypto/test/src/crypto/test/DSTU7564Test.cs +++ b/crypto/test/src/crypto/test/DSTU7564Test.cs @@ -42,6 +42,7 @@ namespace Org.BouncyCastle.Crypto.Tests { } + public override void PerformTest() { base.PerformTest(); @@ -323,8 +324,28 @@ namespace Org.BouncyCastle.Crypto.Tests + " got " + Hex.ToHexString(mac)); } - //test 2 - macBitSize = 384; + //test1a + input = Hex.Decode("0001020304050607"); + key = Hex.Decode("08F4EE6F1BE6903B324C4E27990CB24EF69DD58DBE84813EE0A52F6631239875"); + + expectedMac = Hex.Decode("383A0B11989ABF61B2CF3EB489351EB7C9AEF70CF5A9D6DBD90F340FF151BA2D"); + mac = new byte[macBitSize / 8]; + + dstu7564mac = new Dstu7564Mac(macBitSize); + + dstu7564mac.Init(new KeyParameter(key)); + dstu7564mac.BlockUpdate(input, 0, input.Length); + dstu7564mac.DoFinal(mac, 0); + + if (!Arrays.AreEqual(expectedMac, mac)) + { + Fail("Failed mac test 1a - expected " + + Hex.ToHexString(expectedMac) + + " got " + Hex.ToHexString(mac)); + } + + //test 2 + macBitSize = 384; input = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E"); key = Hex.Decode("2F2E2D2C2B2A292827262524232221201F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100"); @@ -614,7 +635,7 @@ namespace Org.BouncyCastle.Crypto.Tests } [Test] - public void TestFunction() + public void Dstu7564TestFunction() { string resultText = Perform().ToString(); Console.WriteLine(resultText); -- cgit 1.4.1 From 683e29b0f3bd0a15eaf576e12f3e48426e1ead84 Mon Sep 17 00:00:00 2001 From: David Hook Date: Thu, 6 Jul 2017 11:31:12 +1000 Subject: initial DSTU7624 work --- crypto/src/crypto/engines/Dstu7624Engine.cs | 862 ++++++++++++++++++++++++ crypto/src/crypto/engines/Dstu7624WrapEngine.cs | 263 ++++++++ crypto/test/src/crypto/test/DSTU7624Test.cs | 481 +++++++++++++ 3 files changed, 1606 insertions(+) create mode 100644 crypto/src/crypto/engines/Dstu7624Engine.cs create mode 100644 crypto/src/crypto/engines/Dstu7624WrapEngine.cs create mode 100644 crypto/test/src/crypto/test/DSTU7624Test.cs (limited to 'crypto') diff --git a/crypto/src/crypto/engines/Dstu7624Engine.cs b/crypto/src/crypto/engines/Dstu7624Engine.cs new file mode 100644 index 000000000..4699ee5bd --- /dev/null +++ b/crypto/src/crypto/engines/Dstu7624Engine.cs @@ -0,0 +1,862 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * implementation of DSTU 7624 (Kalyna) + */ + public class Dstu7624Engine + : IBlockCipher + { + private const int BITS_IN_WORD = 64; + private const int BITS_IN_BYTE = 8; + + /* Block words size. */ + private const int kNB_128 = 2; + private const int kNB_256 = 4; + private const int kNB_512 = 8; + + /* Key words size. */ + private const int kNK_128 = 2; + private const int kNK_256 = 4; + private const int kNK_512 = 8; + + /* Block bits size. */ + private const int kBLOCK_128 = kNB_128 * BITS_IN_WORD; + private const int kBLOCK_256 = kNB_256 * BITS_IN_WORD; + private const int kBLOCK_512 = kNB_512 * BITS_IN_WORD; + + /* Block bits size. */ + private const int kKEY_128 = kNK_128 * BITS_IN_WORD; + private const int kKEY_256 = kNK_256 * BITS_IN_WORD; + private const int kKEY_512 = kNK_512 * BITS_IN_WORD; + + /* Number of enciphering rounds size depending on key length. */ + private const int kNR_128 = 10; + private const int kNR_256 = 14; + private const int kNR_512 = 18; + + private const int REDUCTION_POLYNOMIAL = 0x011d; /* x^8 + x^4 + x^3 + x^2 + 1 */ + + + private int nb; /* Number of 64-bit words in enciphering block. */ + private int nk; /*< Number of 64-bit words in key. */ + private int roundKeysAmount; /*< Number of enciphering rounds. */ + + private ulong[] internalState = null; /*< Current cipher state. */ + + + private ulong[] workingKey = null; + private ulong[][] roundKeys = null; /*< Round key computed from enciphering key. */ + + + private int blockSizeBits; + private int keySizeBits; + + private bool forEncryption; + + + public Dstu7624Engine(int blockSizeBits, int keySizeBits) + { + this.blockSizeBits = blockSizeBits; + this.keySizeBits = keySizeBits; + + if (blockSizeBits == kBLOCK_128) + { + nb = kBLOCK_128 / BITS_IN_WORD; + if (keySizeBits == kKEY_128) + { + nk = kKEY_128 / BITS_IN_WORD; + roundKeysAmount = kNR_128; + } + else if (keySizeBits == kKEY_256) + { + nk = kKEY_256 / BITS_IN_WORD; + roundKeysAmount = kNR_256; + } + else + { + throw new ArgumentException("Unsupported key size"); + } + } + else if (blockSizeBits == 256) + { + nb = kBLOCK_256 / BITS_IN_WORD; + if (keySizeBits == kKEY_256) + { + nk = kKEY_256 / BITS_IN_WORD; + roundKeysAmount = kNR_256; + } + else if (keySizeBits == kKEY_512) + { + nk = kKEY_512 / BITS_IN_WORD; + roundKeysAmount = kNR_512; + } + else + { + throw new ArgumentException("Unsupported key size"); + } + } + else if (blockSizeBits == kBLOCK_512) + { + nb = kBLOCK_512 / BITS_IN_WORD; + if (keySizeBits == kKEY_512) + { + nk = kKEY_512 / BITS_IN_WORD; + roundKeysAmount = kNR_512; + } + else + { + throw new ArgumentException("Unsupported key size"); + } + } + else + { + throw new ArgumentException("Unsupported block size"); + } + + internalState = new ulong[nb]; + + roundKeys = new ulong[roundKeysAmount + 1][]; + + for (int i = 0; i < roundKeysAmount + 1; i++) + { + roundKeys[i] = new ulong[nb]; + } + } + + + + #region INITIALIZATION + public virtual void Init(bool forEncryption, ICipherParameters parameters) + { + if (parameters is KeyParameter) + { + workingKey = BytesToWords(((KeyParameter)parameters).GetKey()); + + ulong[] kt = new ulong[nb]; + + KeyExpandKT(workingKey, kt); + + KeyExpandEven(workingKey, kt); + + KeyExpandOdd(); + + } + else if (parameters != null) + { + throw new ArgumentException("invalid parameter passed to Dstu7624 init - " + + Platform.GetTypeName(parameters)); + } + + this.forEncryption = forEncryption; + } + + private void KeyExpandKT(ulong[] key, ulong[] kt) + { + ulong[] k0 = new ulong[nb]; + ulong[] k1 = new ulong[nb]; + + internalState = new ulong[nb]; + internalState[0] += (ulong)(nb + nk + 1); + + if (nb == nk) + { + Array.Copy(key, k0, k0.Length); + Array.Copy(key, k1, k1.Length); + } + else + { + Array.Copy(key, 0, k0, 0, nb); + Array.Copy(key, nb, k1, 0, nb); + } + + AddRoundKeyExpand(k0); + + EncryptionRound(); + + XorRoundKeyExpand(k1); + + EncryptionRound(); + + AddRoundKeyExpand(k0); + + EncryptionRound(); + + Array.Copy(internalState, kt, nb); + } + private void KeyExpandEven(ulong[] key, ulong[] kt) + { + ulong[] initial_data = new ulong[nk]; + + ulong[] kt_round = new ulong[nb]; + + ulong[] tmv = new ulong[nb]; + + int round = 0; + + Array.Copy(key, initial_data, nk); + + for (int i = 0; i < nb; i++) + { + tmv[i] = 0x0001000100010001; + } + + while (true) + { + Array.Copy(kt, internalState, nb); + + AddRoundKeyExpand(tmv); + + Array.Copy(internalState, kt_round, nb); + Array.Copy(initial_data, internalState, nb); + + AddRoundKeyExpand(kt_round); + + EncryptionRound(); + + XorRoundKeyExpand(kt_round); + + EncryptionRound(); + + AddRoundKeyExpand(kt_round); + + Array.Copy(internalState, roundKeys[round], nb); + + if (roundKeysAmount == round) + { + break; + } + if (nk != nb) + { + round += 2; + + ShiftLeft(tmv); + + Array.Copy(kt, internalState, nb); + + AddRoundKeyExpand(tmv); + + Array.Copy(internalState, kt_round, nb); + Array.Copy(initial_data, nb, internalState, 0, nb); + + AddRoundKeyExpand(kt_round); + + EncryptionRound(); + + XorRoundKeyExpand(kt_round); + + EncryptionRound(); + + AddRoundKeyExpand(kt_round); + + Array.Copy(internalState, roundKeys[round], nb); + + if (roundKeysAmount == round) + { + break; + } + } + + round += 2; + ShiftLeft(tmv); + + //Rotate initial data array on 1 element left + ulong temp = initial_data[0]; + Array.Copy(initial_data, 1, initial_data, 0, initial_data.Length - 1); + initial_data[initial_data.Length - 1] = temp; + } + } + private void KeyExpandOdd() + { + for (int i = 1; i < roundKeysAmount; i += 2) + { + Array.Copy(roundKeys[i - 1], roundKeys[i], nb); + RotateLeft(roundKeys[i]); + } + } + #endregion + + + public virtual int ProcessBlock(byte[] input, int inOff, byte[] output, int outOff) + { + if (workingKey == null) + throw new InvalidOperationException("Dstu7624 engine not initialised"); + + Check.DataLength(input, inOff, GetBlockSize(), "input buffer too short"); + Check.OutputLength(output, outOff, GetBlockSize(), "output buffer too short"); + + if (forEncryption) + { + Encrypt(input, inOff, output, outOff); + } + else + { + Decrypt(input, inOff, output, outOff); + } + + return GetBlockSize(); + } + + private void Encrypt(byte[] plain, int inOff, byte[] cipherText, int outOff) + { + int round = 0; + + Array.Copy(plain, inOff, plain, 0, blockSizeBits / BITS_IN_BYTE); + Array.Resize(ref plain, blockSizeBits / BITS_IN_BYTE); + + ulong[] plain_ = BytesToWords(plain); + + Array.Copy(plain_, internalState, nb); + + AddRoundKey(round); + + for (round = 1; round < roundKeysAmount; round++) + { + EncryptionRound(); + + XorRoundKey(round); + + } + EncryptionRound(); + + AddRoundKey(roundKeysAmount); + + ulong[] cipherText_ = new ulong[internalState.Length]; + + Array.Copy(internalState, cipherText_, nb); + + byte[] temp = WordsToBytes(cipherText_); + + Array.Copy(temp, 0, cipherText, outOff, temp.Length); + + } + private void Decrypt(byte[] cipherText, int inOff, byte[] decryptedText, int outOff) + { + Array.Copy(cipherText, inOff, cipherText, 0, blockSizeBits / BITS_IN_BYTE); + Array.Resize(ref cipherText, blockSizeBits / BITS_IN_BYTE); + + int round = roundKeysAmount; + + ulong[] cipherText_ = BytesToWords(cipherText); + + Array.Copy(cipherText_, internalState, nb); + + SubRoundKey(round); + + for (round = roundKeysAmount - 1; round > 0; round--) + { + DecryptionRound(); + XorRoundKey(round); + } + + DecryptionRound(); + SubRoundKey(0); + + ulong[] decryptedText_ = new ulong[internalState.Length]; + + Array.Copy(internalState, decryptedText_, nb); + + + byte[] temp = WordsToBytes(decryptedText_); + Array.Copy(temp, 0, decryptedText, outOff, temp.Length); + + + } + + + + + + + + + + private void AddRoundKeyExpand(ulong[] value) + { + for (int i = 0; i < nb; i++) + { + internalState[i] += value[i]; + } + } + + private void EncryptionRound() + { + SubBytes(); + ShiftRows(); + MixColumns(); + } + + private void DecryptionRound() + { + InvMixColumns(); + InvShiftRows(); + InvSubBytes(); + } + + private void RotateLeft(ulong[] state_value) + { + int rotateBytesLength = 2 * state_value.Length + 3; + int bytesLength = state_value.Length * (BITS_IN_WORD / BITS_IN_BYTE); + + + byte[] bytes = WordsToBytes(state_value); + byte[] buffer = new byte[rotateBytesLength]; + + Array.Copy(bytes, buffer, rotateBytesLength); + + Buffer.BlockCopy(bytes, rotateBytesLength, bytes, 0, bytesLength - rotateBytesLength); + + Array.Copy(buffer, 0, bytes, bytesLength - rotateBytesLength, rotateBytesLength); + + var temp = BytesToWords(bytes); + Array.Copy(temp, state_value, state_value.Length); + } + + private void ShiftLeft(ulong[] state_value) + { + for (int i = 0; i < state_value.Length; i++) + { + state_value[i] <<= 1; + } + Array.Reverse(state_value); + } + + private void XorRoundKeyExpand(ulong[] value) + { + for (int i = 0; i < nb; i++) + { + internalState[i] ^= value[i]; + } + } + + private void XorRoundKey(int round) + { + for (int i = 0; i < nb; i++) + { + internalState[i] ^= roundKeys[round][i]; + } + } + + private void ShiftRows() + { + int row, col; + int shift = -1; + + byte[] stateBytes = WordsToBytes(internalState); + + byte[] nstate = new byte[nb * sizeof(ulong)]; + + for (row = 0; row < sizeof(ulong); row++) + { + if (row % (sizeof(ulong) / nb) == 0) + { + shift += 1; + } + + for (col = 0; col < nb; col++) + { + nstate[row + ((col + shift) % nb) * sizeof(ulong)] = stateBytes[row + col * sizeof(ulong)]; + } + } + + internalState = BytesToWords(nstate); + + } + + private void InvShiftRows() + { + int row, col; + int shift = -1; + + byte[] stateBytes = WordsToBytes(internalState); + byte[] nstate = new byte[nb * sizeof(ulong)]; + + for (row = 0; row < sizeof(ulong); row++) + { + if (row % (sizeof(ulong) / nb) == 0) + { + shift += 1; + } + + for (col = 0; col < nb; col++) + { + nstate[row + col * sizeof(ulong)] = stateBytes[row + ((col + shift) % nb) * sizeof(ulong)]; + } + } + + internalState = BytesToWords(nstate); + } + + private ulong[] BytesToWords(byte[] bytes) + { + ulong[] words = new ulong[bytes.Length / sizeof(ulong)]; + + for (int i = 0; i < words.Length; i++) + { + words[i] = BitConverter.ToUInt64(bytes, i * sizeof(ulong)); + + if (!BitConverter.IsLittleEndian) + { + words[i] = ReverseWord(words[i]); + } + } + + return words; + } + + private byte[] WordsToBytes(ulong[] words) + { + byte[] bytes = new byte[words.Length * sizeof(ulong)]; + + byte[] tempBytes = new byte[sizeof(ulong)]; + + for (int i = 0; i < words.Length; ++i) + { + if (!BitConverter.IsLittleEndian) + { + words[i] = ReverseWord(words[i]); + } + + tempBytes = BitConverter.GetBytes(words[i]); + Array.Copy(tempBytes, 0, bytes, i * tempBytes.Length, tempBytes.Length); + } + return bytes; + } + + private ulong ReverseWord(ulong x) + { + byte[] bytes = BitConverter.GetBytes(x); + Array.Reverse(bytes); + return BitConverter.ToUInt64(bytes, 0); + } + + private void AddRoundKey(int round) + { + for (int i = 0; i < nb; ++i) + { + internalState[i] += roundKeys[round][i]; + } + } + + private void SubRoundKey(int round) + { + for (int i = 0; i < nb; ++i) + { + internalState[i] -= roundKeys[round][i]; + } + } + + private void MixColumns() + { + MatrixMultiply(mdsMatrix); + } + + private void InvMixColumns() + { + MatrixMultiply(mdsInvMatrix); + } + + private void MatrixMultiply(byte[][] matrix) + { + int col, row, b; + byte product; + ulong result; + byte[] stateBytes = WordsToBytes(internalState); + + for (col = 0; col < nb; ++col) + { + result = 0; + for (row = sizeof(ulong) - 1; row >= 0; --row) + { + product = 0; + for (b = sizeof(ulong) - 1; b >= 0; --b) + { + product ^= MultiplyGF(stateBytes[b + col * sizeof(ulong)], matrix[row][b]); + } + result |= (ulong)product << (row * sizeof(ulong)); + } + internalState[col] = result; + } + } + + private byte MultiplyGF(byte x, byte y) + { + byte r = 0; + byte hbit = 0; + + for (int i = 0; i < BITS_IN_BYTE; i++) + { + if ((y & 0x01) == 1) + { + r ^= x; + } + + hbit = (byte)(x & 0x80); + + x <<= 1; + + if (hbit == 0x80) + { + x = (byte)((int)x ^ REDUCTION_POLYNOMIAL); + } + y >>= 1; + } + return r; + } + + private void SubBytes() + { + for (int i = 0; i < nb; i++) + { + internalState[i] = sboxesForEncryption[0][internalState[i] & 0x00000000000000FF] | + ((ulong)sboxesForEncryption[1][(internalState[i] & 0x000000000000FF00) >> 8] << 8) | + ((ulong)sboxesForEncryption[2][(internalState[i] & 0x0000000000FF0000) >> 16] << 16) | + ((ulong)sboxesForEncryption[3][(internalState[i] & 0x00000000FF000000) >> 24] << 24) | + ((ulong)sboxesForEncryption[0][(internalState[i] & 0x000000FF00000000) >> 32] << 32) | + ((ulong)sboxesForEncryption[1][(internalState[i] & 0x0000FF0000000000) >> 40] << 40) | + ((ulong)sboxesForEncryption[2][(internalState[i] & 0x00FF000000000000) >> 48] << 48) | + ((ulong)sboxesForEncryption[3][(internalState[i] & 0xFF00000000000000) >> 56] << 56); + } + } + + private void InvSubBytes() + { + for (int i = 0; i < nb; i++) + { + internalState[i] = sboxesForDecryption[0][internalState[i] & 0x00000000000000FF] | + ((ulong)sboxesForDecryption[1][(internalState[i] & 0x000000000000FF00) >> 8] << 8) | + ((ulong)sboxesForDecryption[2][(internalState[i] & 0x0000000000FF0000) >> 16] << 16) | + ((ulong)sboxesForDecryption[3][(internalState[i] & 0x00000000FF000000) >> 24] << 24) | + ((ulong)sboxesForDecryption[0][(internalState[i] & 0x000000FF00000000) >> 32] << 32) | + ((ulong)sboxesForDecryption[1][(internalState[i] & 0x0000FF0000000000) >> 40] << 40) | + ((ulong)sboxesForDecryption[2][(internalState[i] & 0x00FF000000000000) >> 48] << 48) | + ((ulong)sboxesForDecryption[3][(internalState[i] & 0xFF00000000000000) >> 56] << 56); + } + } + + + #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 byte[][] sboxesForEncryption = + { + 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 byte[][] sboxesForDecryption = + { + new byte[] + { + 0xa4, 0xa2, 0xa9, 0xc5, 0x4e, 0xc9, 0x03, 0xd9, 0x7e, 0x0f, 0xd2, 0xad, 0xe7, 0xd3, 0x27, 0x5b, + 0xe3, 0xa1, 0xe8, 0xe6, 0x7c, 0x2a, 0x55, 0x0c, 0x86, 0x39, 0xd7, 0x8d, 0xb8, 0x12, 0x6f, 0x28, + 0xcd, 0x8a, 0x70, 0x56, 0x72, 0xf9, 0xbf, 0x4f, 0x73, 0xe9, 0xf7, 0x57, 0x16, 0xac, 0x50, 0xc0, + 0x9d, 0xb7, 0x47, 0x71, 0x60, 0xc4, 0x74, 0x43, 0x6c, 0x1f, 0x93, 0x77, 0xdc, 0xce, 0x20, 0x8c, + 0x99, 0x5f, 0x44, 0x01, 0xf5, 0x1e, 0x87, 0x5e, 0x61, 0x2c, 0x4b, 0x1d, 0x81, 0x15, 0xf4, 0x23, + 0xd6, 0xea, 0xe1, 0x67, 0xf1, 0x7f, 0xfe, 0xda, 0x3c, 0x07, 0x53, 0x6a, 0x84, 0x9c, 0xcb, 0x02, + 0x83, 0x33, 0xdd, 0x35, 0xe2, 0x59, 0x5a, 0x98, 0xa5, 0x92, 0x64, 0x04, 0x06, 0x10, 0x4d, 0x1c, + 0x97, 0x08, 0x31, 0xee, 0xab, 0x05, 0xaf, 0x79, 0xa0, 0x18, 0x46, 0x6d, 0xfc, 0x89, 0xd4, 0xc7, + 0xff, 0xf0, 0xcf, 0x42, 0x91, 0xf8, 0x68, 0x0a, 0x65, 0x8e, 0xb6, 0xfd, 0xc3, 0xef, 0x78, 0x4c, + 0xcc, 0x9e, 0x30, 0x2e, 0xbc, 0x0b, 0x54, 0x1a, 0xa6, 0xbb, 0x26, 0x80, 0x48, 0x94, 0x32, 0x7d, + 0xa7, 0x3f, 0xae, 0x22, 0x3d, 0x66, 0xaa, 0xf6, 0x00, 0x5d, 0xbd, 0x4a, 0xe0, 0x3b, 0xb4, 0x17, + 0x8b, 0x9f, 0x76, 0xb0, 0x24, 0x9a, 0x25, 0x63, 0xdb, 0xeb, 0x7a, 0x3e, 0x5c, 0xb3, 0xb1, 0x29, + 0xf2, 0xca, 0x58, 0x6e, 0xd8, 0xa8, 0x2f, 0x75, 0xdf, 0x14, 0xfb, 0x13, 0x49, 0x88, 0xb2, 0xec, + 0xe4, 0x34, 0x2d, 0x96, 0xc6, 0x3a, 0xed, 0x95, 0x0e, 0xe5, 0x85, 0x6b, 0x40, 0x21, 0x9b, 0x09, + 0x19, 0x2b, 0x52, 0xde, 0x45, 0xa3, 0xfa, 0x51, 0xc2, 0xb5, 0xd1, 0x90, 0xb9, 0xf3, 0x37, 0xc1, + 0x0d, 0xba, 0x41, 0x11, 0x38, 0x7b, 0xbe, 0xd0, 0xd5, 0x69, 0x36, 0xc8, 0x62, 0x1b, 0x82, 0x8f + }, + + new byte[] + { + 0x83, 0xf2, 0x2a, 0xeb, 0xe9, 0xbf, 0x7b, 0x9c, 0x34, 0x96, 0x8d, 0x98, 0xb9, 0x69, 0x8c, 0x29, + 0x3d, 0x88, 0x68, 0x06, 0x39, 0x11, 0x4c, 0x0e, 0xa0, 0x56, 0x40, 0x92, 0x15, 0xbc, 0xb3, 0xdc, + 0x6f, 0xf8, 0x26, 0xba, 0xbe, 0xbd, 0x31, 0xfb, 0xc3, 0xfe, 0x80, 0x61, 0xe1, 0x7a, 0x32, 0xd2, + 0x70, 0x20, 0xa1, 0x45, 0xec, 0xd9, 0x1a, 0x5d, 0xb4, 0xd8, 0x09, 0xa5, 0x55, 0x8e, 0x37, 0x76, + 0xa9, 0x67, 0x10, 0x17, 0x36, 0x65, 0xb1, 0x95, 0x62, 0x59, 0x74, 0xa3, 0x50, 0x2f, 0x4b, 0xc8, + 0xd0, 0x8f, 0xcd, 0xd4, 0x3c, 0x86, 0x12, 0x1d, 0x23, 0xef, 0xf4, 0x53, 0x19, 0x35, 0xe6, 0x7f, + 0x5e, 0xd6, 0x79, 0x51, 0x22, 0x14, 0xf7, 0x1e, 0x4a, 0x42, 0x9b, 0x41, 0x73, 0x2d, 0xc1, 0x5c, + 0xa6, 0xa2, 0xe0, 0x2e, 0xd3, 0x28, 0xbb, 0xc9, 0xae, 0x6a, 0xd1, 0x5a, 0x30, 0x90, 0x84, 0xf9, + 0xb2, 0x58, 0xcf, 0x7e, 0xc5, 0xcb, 0x97, 0xe4, 0x16, 0x6c, 0xfa, 0xb0, 0x6d, 0x1f, 0x52, 0x99, + 0x0d, 0x4e, 0x03, 0x91, 0xc2, 0x4d, 0x64, 0x77, 0x9f, 0xdd, 0xc4, 0x49, 0x8a, 0x9a, 0x24, 0x38, + 0xa7, 0x57, 0x85, 0xc7, 0x7c, 0x7d, 0xe7, 0xf6, 0xb7, 0xac, 0x27, 0x46, 0xde, 0xdf, 0x3b, 0xd7, + 0x9e, 0x2b, 0x0b, 0xd5, 0x13, 0x75, 0xf0, 0x72, 0xb6, 0x9d, 0x1b, 0x01, 0x3f, 0x44, 0xe5, 0x87, + 0xfd, 0x07, 0xf1, 0xab, 0x94, 0x18, 0xea, 0xfc, 0x3a, 0x82, 0x5f, 0x05, 0x54, 0xdb, 0x00, 0x8b, + 0xe3, 0x48, 0x0c, 0xca, 0x78, 0x89, 0x0a, 0xff, 0x3e, 0x5b, 0x81, 0xee, 0x71, 0xe2, 0xda, 0x2c, + 0xb8, 0xb5, 0xcc, 0x6e, 0xa8, 0x6b, 0xad, 0x60, 0xc6, 0x08, 0x04, 0x02, 0xe8, 0xf5, 0x4f, 0xa4, + 0xf3, 0xc0, 0xce, 0x43, 0x25, 0x1c, 0x21, 0x33, 0x0f, 0xaf, 0x47, 0xed, 0x66, 0x63, 0x93, 0xaa + }, + + new byte[] + { + 0x45, 0xd4, 0x0b, 0x43, 0xf1, 0x72, 0xed, 0xa4, 0xc2, 0x38, 0xe6, 0x71, 0xfd, 0xb6, 0x3a, 0x95, + 0x50, 0x44, 0x4b, 0xe2, 0x74, 0x6b, 0x1e, 0x11, 0x5a, 0xc6, 0xb4, 0xd8, 0xa5, 0x8a, 0x70, 0xa3, + 0xa8, 0xfa, 0x05, 0xd9, 0x97, 0x40, 0xc9, 0x90, 0x98, 0x8f, 0xdc, 0x12, 0x31, 0x2c, 0x47, 0x6a, + 0x99, 0xae, 0xc8, 0x7f, 0xf9, 0x4f, 0x5d, 0x96, 0x6f, 0xf4, 0xb3, 0x39, 0x21, 0xda, 0x9c, 0x85, + 0x9e, 0x3b, 0xf0, 0xbf, 0xef, 0x06, 0xee, 0xe5, 0x5f, 0x20, 0x10, 0xcc, 0x3c, 0x54, 0x4a, 0x52, + 0x94, 0x0e, 0xc0, 0x28, 0xf6, 0x56, 0x60, 0xa2, 0xe3, 0x0f, 0xec, 0x9d, 0x24, 0x83, 0x7e, 0xd5, + 0x7c, 0xeb, 0x18, 0xd7, 0xcd, 0xdd, 0x78, 0xff, 0xdb, 0xa1, 0x09, 0xd0, 0x76, 0x84, 0x75, 0xbb, + 0x1d, 0x1a, 0x2f, 0xb0, 0xfe, 0xd6, 0x34, 0x63, 0x35, 0xd2, 0x2a, 0x59, 0x6d, 0x4d, 0x77, 0xe7, + 0x8e, 0x61, 0xcf, 0x9f, 0xce, 0x27, 0xf5, 0x80, 0x86, 0xc7, 0xa6, 0xfb, 0xf8, 0x87, 0xab, 0x62, + 0x3f, 0xdf, 0x48, 0x00, 0x14, 0x9a, 0xbd, 0x5b, 0x04, 0x92, 0x02, 0x25, 0x65, 0x4c, 0x53, 0x0c, + 0xf2, 0x29, 0xaf, 0x17, 0x6c, 0x41, 0x30, 0xe9, 0x93, 0x55, 0xf7, 0xac, 0x68, 0x26, 0xc4, 0x7d, + 0xca, 0x7a, 0x3e, 0xa0, 0x37, 0x03, 0xc1, 0x36, 0x69, 0x66, 0x08, 0x16, 0xa7, 0xbc, 0xc5, 0xd3, + 0x22, 0xb7, 0x13, 0x46, 0x32, 0xe8, 0x57, 0x88, 0x2b, 0x81, 0xb2, 0x4e, 0x64, 0x1c, 0xaa, 0x91, + 0x58, 0x2e, 0x9b, 0x5c, 0x1b, 0x51, 0x73, 0x42, 0x23, 0x01, 0x6e, 0xf3, 0x0d, 0xbe, 0x3d, 0x0a, + 0x2d, 0x1f, 0x67, 0x33, 0x19, 0x7b, 0x5e, 0xea, 0xde, 0x8b, 0xcb, 0xa9, 0x8c, 0x8d, 0xad, 0x49, + 0x82, 0xe4, 0xba, 0xc3, 0x15, 0xd1, 0xe0, 0x89, 0xfc, 0xb1, 0xb9, 0xb5, 0x07, 0x79, 0xb8, 0xe1 + }, + + new byte[] + { + 0xb2, 0xb6, 0x23, 0x11, 0xa7, 0x88, 0xc5, 0xa6, 0x39, 0x8f, 0xc4, 0xe8, 0x73, 0x22, 0x43, 0xc3, + 0x82, 0x27, 0xcd, 0x18, 0x51, 0x62, 0x2d, 0xf7, 0x5c, 0x0e, 0x3b, 0xfd, 0xca, 0x9b, 0x0d, 0x0f, + 0x79, 0x8c, 0x10, 0x4c, 0x74, 0x1c, 0x0a, 0x8e, 0x7c, 0x94, 0x07, 0xc7, 0x5e, 0x14, 0xa1, 0x21, + 0x57, 0x50, 0x4e, 0xa9, 0x80, 0xd9, 0xef, 0x64, 0x41, 0xcf, 0x3c, 0xee, 0x2e, 0x13, 0x29, 0xba, + 0x34, 0x5a, 0xae, 0x8a, 0x61, 0x33, 0x12, 0xb9, 0x55, 0xa8, 0x15, 0x05, 0xf6, 0x03, 0x06, 0x49, + 0xb5, 0x25, 0x09, 0x16, 0x0c, 0x2a, 0x38, 0xfc, 0x20, 0xf4, 0xe5, 0x7f, 0xd7, 0x31, 0x2b, 0x66, + 0x6f, 0xff, 0x72, 0x86, 0xf0, 0xa3, 0x2f, 0x78, 0x00, 0xbc, 0xcc, 0xe2, 0xb0, 0xf1, 0x42, 0xb4, + 0x30, 0x5f, 0x60, 0x04, 0xec, 0xa5, 0xe3, 0x8b, 0xe7, 0x1d, 0xbf, 0x84, 0x7b, 0xe6, 0x81, 0xf8, + 0xde, 0xd8, 0xd2, 0x17, 0xce, 0x4b, 0x47, 0xd6, 0x69, 0x6c, 0x19, 0x99, 0x9a, 0x01, 0xb3, 0x85, + 0xb1, 0xf9, 0x59, 0xc2, 0x37, 0xe9, 0xc8, 0xa0, 0xed, 0x4f, 0x89, 0x68, 0x6d, 0xd5, 0x26, 0x91, + 0x87, 0x58, 0xbd, 0xc9, 0x98, 0xdc, 0x75, 0xc0, 0x76, 0xf5, 0x67, 0x6b, 0x7e, 0xeb, 0x52, 0xcb, + 0xd1, 0x5b, 0x9f, 0x0b, 0xdb, 0x40, 0x92, 0x1a, 0xfa, 0xac, 0xe4, 0xe1, 0x71, 0x1f, 0x65, 0x8d, + 0x97, 0x9e, 0x95, 0x90, 0x5d, 0xb7, 0xc1, 0xaf, 0x54, 0xfb, 0x02, 0xe0, 0x35, 0xbb, 0x3a, 0x4d, + 0xad, 0x2c, 0x3d, 0x56, 0x08, 0x1b, 0x4a, 0x93, 0x6a, 0xab, 0xb8, 0x7a, 0xf2, 0x7d, 0xda, 0x3f, + 0xfe, 0x3e, 0xbe, 0xea, 0xaa, 0x44, 0xc6, 0xd0, 0x36, 0x48, 0x70, 0x96, 0x77, 0x24, 0x53, 0xdf, + 0xf3, 0x83, 0x28, 0x32, 0x45, 0x1e, 0xa4, 0xd3, 0xa2, 0x46, 0x6e, 0x9c, 0xdd, 0x63, 0xd4, 0x9d + } + }; + #endregion + + + + public virtual string AlgorithmName + { + get { return "Dstu7624"; } + } + + public virtual int GetBlockSize() + { + return blockSizeBits / BITS_IN_BYTE; + } + + public virtual bool IsPartialBlockOkay + { + get { return false; } + } + + public virtual void Reset() + { + + } + + } +} diff --git a/crypto/src/crypto/engines/Dstu7624WrapEngine.cs b/crypto/src/crypto/engines/Dstu7624WrapEngine.cs new file mode 100644 index 000000000..bfe8d9c1c --- /dev/null +++ b/crypto/src/crypto/engines/Dstu7624WrapEngine.cs @@ -0,0 +1,263 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using System.Collections.Generic; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Engines +{ + public class Dstu7624WrapEngine : IWrapper + { + private const int BYTES_IN_INTEGER = 4; + + private KeyParameter param; + private Dstu7624Engine engine; + private bool forWrapping; + private int blockSize; + + private byte[] buffer; + private byte[] intArray; + + private readonly byte[] checkSumArray, zeroArray; + + + public Dstu7624WrapEngine(int blockSizeBits, int keySizeBits) + { + engine = new Dstu7624Engine(blockSizeBits, keySizeBits); + param = null; + + blockSize = blockSizeBits / 8; + buffer = new byte[blockSize]; + + intArray = new byte[BYTES_IN_INTEGER]; + + checkSumArray = new byte[blockSize]; + zeroArray = new byte[blockSize]; + } + + + public string AlgorithmName + { + get { return "Dstu7624WrapEngine"; } + } + + public void Init(bool forWrapping, ICipherParameters parameters) + { + this.forWrapping = forWrapping; + + if (parameters is KeyParameter) + { + this.param = (KeyParameter)parameters; + + engine.Init(forWrapping, param); + } + else + { + throw new ArgumentException("Bad parameters passed to Dstu7624WrapEngine"); + } + } + + public byte[] Wrap(byte[] input, int inOff, int length) + { + if (!forWrapping) + { + throw new InvalidOperationException("Not set for wrapping"); + } + + if ((input.Length - inOff) % blockSize != 0) + { + throw new ArgumentException("Padding not supported"); + } + + int n = 2 * (1 + input.Length / blockSize); + + int V = (n - 1) * 6; + + buffer = new byte[input.Length - inOff + blockSize]; + Array.Copy(input, inOff, buffer, 0, input.Length - inOff); + //Console.WriteLine(Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(buffer)); + + + + byte[] B = new byte[blockSize / 2]; + Array.Copy(buffer, 0, B, 0, blockSize / 2); + //Console.WriteLine("B0: "+ Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(B)); + + + List bTemp = new List(); + + int bHalfBlocksLen = buffer.Length - blockSize / 2; + int bufOff = blockSize / 2; + while (bHalfBlocksLen != 0) + { + byte[] temp = new byte[blockSize / 2]; + Array.Copy(buffer, bufOff, temp, 0, blockSize / 2); + //Console.WriteLine(Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(buffer)); + //Console.WriteLine(buffer.Length); + //Console.WriteLine("b: " + Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(temp)); + + bTemp.Add(temp); + + bHalfBlocksLen -= blockSize / 2; + bufOff += blockSize / 2; + } + + + + for (int j = 0; j < V; j++) + { + Array.Copy(B, 0, buffer, 0, blockSize / 2); + Array.Copy(bTemp[0], 0, buffer, blockSize / 2, blockSize / 2); + + engine.ProcessBlock(buffer, 0, buffer, 0); + + intTobytes(j + 1, intArray, 0); + for (int byteNum = 0; byteNum < BYTES_IN_INTEGER; byteNum++) + { + buffer[byteNum + blockSize / 2] ^= intArray[byteNum]; + } + + Array.Copy(buffer, blockSize / 2, B, 0, blockSize / 2); + + for (int i = 2; i < n; i++) + { + Array.Copy(bTemp[i - 1], 0, bTemp[i - 2], 0, blockSize / 2); + } + + Array.Copy(buffer, 0, bTemp[n - 2], 0, blockSize / 2); + + //Console.WriteLine("B" + j.ToString() + ": " + Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(B)); + //Console.WriteLine("b: " + Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(bTemp[0])); + //Console.WriteLine("b: " + Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(bTemp[1])); + //Console.WriteLine("b: " + Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(bTemp[2])); + + //Console.WriteLine(Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(buffer)); + } + + + Array.Copy(B, 0, buffer, 0, blockSize / 2); + bufOff = blockSize / 2; + + for (int i = 0; i < n - 1; i++) + { + Array.Copy(bTemp[i], 0, buffer, bufOff, blockSize / 2); + bufOff += blockSize / 2; + } + + return buffer; + } + + public byte[] Unwrap(byte[] input, int inOff, int length) + { + if (forWrapping) + { + throw new InvalidOperationException("not set for unwrapping"); + } + + if ((input.Length - inOff) % blockSize != 0) + { + throw new ArgumentException("Padding not supported"); + } + + int n = 2 * input.Length / blockSize; + + int V = (n - 1) * 6; + + buffer = new byte[input.Length - inOff]; + Array.Copy(input, inOff, buffer, 0, input.Length - inOff); + + byte[] B = new byte[blockSize / 2]; + Array.Copy(buffer, 0, B, 0, blockSize / 2); + //Console.WriteLine("B18: " + Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(B)); + + List bTemp = new List(); + + int bHalfBlocksLen = buffer.Length - blockSize / 2; + int bufOff = blockSize / 2; + while (bHalfBlocksLen != 0) + { + byte[] temp = new byte[blockSize / 2]; + Array.Copy(buffer, bufOff, temp, 0, blockSize / 2); + //Console.WriteLine(Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(buffer)); + //Console.WriteLine(buffer.Length); + //Console.WriteLine("b: " + Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(temp)); + + bTemp.Add(temp); + + bHalfBlocksLen -= blockSize / 2; + bufOff += blockSize / 2; + } + + + for (int j = 0; j < V; j++) + { + Array.Copy(bTemp[n - 2], 0, buffer, 0, blockSize / 2); + Array.Copy(B, 0, buffer, blockSize / 2, blockSize / 2); + intTobytes(V - j, intArray, 0); + for (int byteNum = 0; byteNum < BYTES_IN_INTEGER; byteNum++) + { + buffer[byteNum + blockSize / 2] ^= intArray[byteNum]; + } + + //Console.WriteLine(Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(buffer)); + + engine.ProcessBlock(buffer, 0, buffer, 0); + + //Console.WriteLine(Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(buffer)); + + Array.Copy(buffer, 0, B, 0, blockSize / 2); + + for (int i = 2; i < n; i++) + { + Array.Copy(bTemp[n - i - 1], 0, bTemp[n - i], 0, blockSize / 2); + } + + Array.Copy(buffer, blockSize / 2, bTemp[0], 0, blockSize / 2); + + //Console.WriteLine("B" + (V - j - 1).ToString() + ": " + Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(B)); + //Console.WriteLine("b: " + Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(bTemp[0])); + //Console.WriteLine("b: " + Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(bTemp[1])); + //Console.WriteLine("b: " + Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(bTemp[2])); + + //Console.WriteLine(Org.BouncyCastle.Utilities.Encoders.Hex.ToHexString(buffer)); + } + + + Array.Copy(B, 0, buffer, 0, blockSize / 2); + bufOff = blockSize / 2; + + for (int i = 0; i < n - 1; i++) + { + Array.Copy(bTemp[i], 0, buffer, bufOff, blockSize / 2); + bufOff += blockSize / 2; + } + + + Array.Copy(buffer, buffer.Length - blockSize, checkSumArray, 0, blockSize); + + + if (!Arrays.AreEqual(checkSumArray, zeroArray)) + { + throw new InvalidCipherTextException("checksum failed"); + } + else + { + Array.Resize(ref buffer, buffer.Length - blockSize); + } + + return buffer; + } + + //int to array of bytes + private static void intTobytes( + int num, + byte[] outBytes, + int outOff) + { + outBytes[outOff + 3] = (byte)(num >> 24); + outBytes[outOff + 2] = (byte)(num >> 16); + outBytes[outOff + 1] = (byte)(num >> 8); + outBytes[outOff] = (byte)num; + } + } +} diff --git a/crypto/test/src/crypto/test/DSTU7624Test.cs b/crypto/test/src/crypto/test/DSTU7624Test.cs new file mode 100644 index 000000000..5c06fd5d1 --- /dev/null +++ b/crypto/test/src/crypto/test/DSTU7624Test.cs @@ -0,0 +1,481 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tests +{ + [TestFixture] + public class Dstu7624Test : CipherTest + { + public Dstu7624Test() + : base(tests, new Dstu7624Engine(256, 256), new KeyParameter(new byte[32])) { } + + + + internal static SimpleTest[] tests = new SimpleTest[] + { + + //ECB mode + /* + new KBlockCipherVectorTest(0, new Dstu7624Engine(128, 128), new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F")), "101112131415161718191A1B1C1D1E1F", "81BF1C7D779BAC20E1C9EA39B4D2AD06"), + new KBlockCipherVectorTest(1, new Dstu7624Engine(128, 256), new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F")), "202122232425262728292A2B2C2D2E2F", "58EC3E091000158A1148F7166F334F14"), + new KBlockCipherVectorTest(2, new Dstu7624Engine(256, 256), new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F")), "202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F", "F66E3D570EC92135AEDAE323DCBD2A8CA03963EC206A0D5A88385C24617FD92C"), + new KBlockCipherVectorTest(3, new Dstu7624Engine(256, 512), new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F")), "404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F", "606990E9E6B7B67A4BD6D893D72268B78E02C83C3CD7E102FD2E74A8FDFE5DD9"), + new KBlockCipherVectorTest(4, new Dstu7624Engine(512, 512), new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F")), "404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F", "4A26E31B811C356AA61DD6CA0596231A67BA8354AA47F3A13E1DEEC320EB56B895D0F417175BAB662FD6F134BB15C86CCB906A26856EFEB7C5BC6472940DD9D9"), + */ + //CTR mode + // new BlockCipherVectorTest(5, new KCtrBlockCipher(new Dstu7624Engine(128, 128)), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F")), Hex.Decode("101112131415161718191A1B1C1D1E1F")), "202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748", "A90A6B9780ABDFDFF64D14F5439E88F266DC50EDD341528DD5E698E2F000CE21F872DAF9FE1811844A"), + /* + //CFB mode (THERE ARE DIFFERENCE IN LAST BLOCK PROCESSING, SO KBufferedBlockCipher WRAPPER IS USED) + new KBlockCipherVectorTest(6, new KCfbBlockCipher(new Dstu7624Engine(128, 128), 128), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F")), Hex.Decode("101112131415161718191A1B1C1D1E1F")), "202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F", "A19E3E5E53BE8A07C9E0C01298FF83291F8EE6212110BE3FA5C72C88A082520B265570FE28680719D9B4465E169BC37A"), + new KBlockCipherVectorTest(7, new KCfbBlockCipher(new Dstu7624Engine(256, 256), 128), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F")), Hex.Decode("202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F")), "404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F90", "E07821AF642F4B1DC071166F2D329763C2CF3B9E39CD0B52BDD33A0DC7B6B6BB201C4A1CD0F5DCB693ABEEA120DACA3A29C73D1D6E87FD75B7DE9E3BE4D256791C2E44583DE8E061E45834A24262BDEBBE"), + new KBlockCipherVectorTest(8, new KCfbBlockCipher(new Dstu7624Engine(128, 256), 64), new ParametersWithIV(new KeyParameter(Hex.Decode("1F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100")), Hex.Decode("2F2E2D2C2B2A29282726252423222120")), "26319A368D85DE43DD5FDB928D91A441493D8CE07B64797C8F9676C5921CD1EA743F5E2777C327AC58", "5F5E5D5C5B5A595857565554535251504F4E4D4C4B4A494847464544434241403F3E3D3C3B3A393837"), + new KBlockCipherVectorTest(9, new KCfbBlockCipher(new Dstu7624Engine(256, 256), 256), new ParametersWithIV(new KeyParameter(Hex.Decode("1F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100")), Hex.Decode("3F3E3D3C3B3A393837363534333231302F2E2D2C2B2A29282726252423222120")), "7758A939DD6BD00CAF9153E5A5D5A66129105CA1EA54A97C06FA4A40960A068F61C3E424DE950151AC46879D84A3BCC24EC8FB69008DAF016EF9832FFD3DB39D02185FDB782DC28EAC27B35179FCA40640", "9F9E9D9C9B9A999897969594939291908F8E8D8C8B8A898887868584838281807F7E7D7C7B7A797877767574737271706F6E6D6C6B6A696867666564636261605F5E5D5C5B5A595857565554535251504F"), + new KBlockCipherVectorTest(10, new KCfbBlockCipher(new Dstu7624Engine(256, 512), 256), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F")), Hex.Decode("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F")), "606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0", "0008F28A82D2D01D23BFB2F8BB4F06D8FE73BA4F48A2977585570ED3818323A6DBAD3D9DD580D9D8F787CE55FAB90735F6B2D6152D56C0C787E6F4B6A2F557DF707A671D06AED196DD7D7E2320D8E45C4C"), + new KBlockCipherVectorTest(11, new KCfbBlockCipher(new Dstu7624Engine(256, 512), 256), new ParametersWithIV(new KeyParameter(Hex.Decode("3F3E3D3C3B3A393837363534333231302F2E2D2C2B2A292827262524232221201F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100")), Hex.Decode("5F5E5D5C5B5A595857565554535251504F4E4D4C4B4A49484746454443424140")), "98E122708FDABB1B1A5765C396DC79D7573221EC486ADDABD1770B147A6DD00BDD5E4F1496D4D573923F9809EEEEF46B063C64A5E875E77E65EC6832ECE3C24A4B8FD40B04088CBEE2CDECE4DC3CC5573A", "BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0AFAEADACABAAA9A8A7A6A5A4A3A2A1A09F9E9D9C9B9A999897969594939291908F8E8D8C8B8A898887868584838281807F7E7D7C7B7A797877767574737271706F"), + new KBlockCipherVectorTest(12, new KCfbBlockCipher(new Dstu7624Engine(512, 512), 512), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F")), Hex.Decode("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F")), "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0", "CAA761980599B3ED2E945C41891BAD95F72B11C73ED26536A6847458BC76C827357156B4B3FE0DC1877F5B9F17B866C37B21D89531DB48007D05DEC928B06766C67D6F3F4C2B82D7A836FAD160905C1C7576243877DC3ADE4AA057966E0023F069"), + new KBlockCipherVectorTest(13, new KCfbBlockCipher(new Dstu7624Engine(512, 512), 512), new ParametersWithIV(new KeyParameter(Hex.Decode("3F3E3D3C3B3A393837363534333231302F2E2D2C2B2A292827262524232221201F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100")), Hex.Decode("7F7E7D7C7B7A797877767574737271706F6E6D6C6B6A696867666564636261605F5E5D5C5B5A595857565554535251504F4E4D4C4B4A49484746454443424140")), "06C061A4A66DFC0910034B3CFBDC4206D8908241C56BF41C4103CFD6DF322210B87F57EAE9F9AD815E606a7D1E8E6BD7CB1EBFBDBCB085C2D06BF3CC1586CB2E88C9155E95B4872D86B49D80F5745B605EAF488AA520A717A92F4D68838E42C995", "EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C4C3C2C1C0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0AFAEADACABAAA9A8A7A6A5A4A3A2A1A09F9E9D9C9B9A999897969594939291908F"), + */ + //CBC mode (PADDING NOT SUPPORTED) + new BlockCipherVectorTest(14, new CbcBlockCipher(new Dstu7624Engine(128, 128)), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F")), Hex.Decode("101112131415161718191A1B1C1D1E1F")), "202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F", "A73625D7BE994E85469A9FAABCEDAAB6DBC5F65DD77BB35E06BD7D1D8EAFC8624D6CB31CE189C82B8979F2936DE9BF14"), + new BlockCipherVectorTest(15, new CbcBlockCipher(new Dstu7624Engine(128, 128)), new ParametersWithIV(new KeyParameter(Hex.Decode("0F0E0D0C0B0A09080706050403020100")), Hex.Decode("1F1E1D1C1B1A19181716151413121110")), "88F2F048BA696170E3818915E0DBC0AFA6F141FEBC2F817138DA4AAB2DBF9CE490A488C9C82AC83FB0A6C0EEB64CFD22", "4F4E4D4C4B4A494847464544434241403F3E3D3C3B3A393837363534333231302F2E2D2C2B2A29282726252423222120"), + new BlockCipherVectorTest(16, new CbcBlockCipher(new Dstu7624Engine(128, 256)), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F")), Hex.Decode("202122232425262728292A2B2C2D2E2F")), "303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D8000", "13EA15843AD14C50BC03ECEF1F43E398E4217752D3EB046AC393DACC5CA1D6FA0EB9FCEB229362B4F1565527EE3D8433"), + new BlockCipherVectorTest(17, new CbcBlockCipher(new Dstu7624Engine(128, 256)), new ParametersWithIV(new KeyParameter(Hex.Decode("1F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100")), Hex.Decode("2F2E2D2C2B2A29282726252423222120")), "BC8F026FC603ECE05C24FDE87542730999B381870882AC0535D4368C4BABD81B884E96E853EE7E055262D9D204FBE212", "5F5E5D5C5B5A595857565554535251504F4E4D4C4B4A494847464544434241403F3E3D3C3B3A39383736353433323130"), + new BlockCipherVectorTest(18, new CbcBlockCipher(new Dstu7624Engine(256, 256)), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F")), Hex.Decode("202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F")), "404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F", "9CDFDAA75929E7C2A5CFC1BF16B42C5AE3886D0258E8C577DC01DAF62D185FB999B9867736B87110F5F1BC7481912C593F48FF79E2AFDFAB9F704A277EC3E557B1B0A9F223DAE6ED5AF591C4F2D6FB22E48334F5E9B96B1A2EA5200F30A406CE"), + new BlockCipherVectorTest(19, new CbcBlockCipher(new Dstu7624Engine(256, 512)), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F")), Hex.Decode("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F")), "606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF", "B8A2474578C2FEBF3F94703587BD5FDC3F4A4D2F43575B6144A1E1031FB3D1452B7FD52F5E3411461DAC506869FF8D2FAEF4FEE60379AE00B33AA3EAF911645AF8091CD8A45D141D1FB150E5A01C1F26FF3DBD26AC4225EC7577B2CE57A5B0FF"), + new BlockCipherVectorTest(20, new CbcBlockCipher(new Dstu7624Engine(256, 512)), new ParametersWithIV(new KeyParameter(Hex.Decode("3F3E3D3C3B3A393837363534333231302F2E2D2C2B2A292827262524232221201F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100")), Hex.Decode("5F5E5D5C5B5A595857565554535251504F4E4D4C4B4A49484746454443424140")), "C69A59E10D00F087319B62288A57417C074EAD07C732A87055F0A5AD2BB288105705C45E091A9A6726E9672DC7D8C76FC45C782BCFEF7C39D94DEB84B17035BC8651255A0D34373451B6E1A2C827DB97566C9FF5506C5579F982A0EFC5BA7C28", "BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0AFAEADACABAAA9A8A7A6A5A4A3A2A1A09F9E9D9C9B9A999897969594939291908F8E8D8C8B8A898887868584838281807F7E7D7C7B7A797877767574737271706F6E6D6C6B6A69686766656463626160"), + new BlockCipherVectorTest(21, new CbcBlockCipher(new Dstu7624Engine(512, 512)), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F")), Hex.Decode("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F")), "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF", "D4739B829EF901B24C1162AE4FDEF897EDA41FAC7F5770CDC90E1D1CDF124E8D7831E06B4498A4B6F6EC815DF2461DC99BB0449B0F09FCAA2C84090534BCC9329626FD74EF8F0A0BCB5765184629C3CBF53B0FB134F6D0421174B1C4E884D1CD1069A7AD19752DCEBF655842E79B7858BDE01390A760D85E88925BFE38B0FA57"), + new BlockCipherVectorTest(22, new CbcBlockCipher(new Dstu7624Engine(512, 512)), new ParametersWithIV(new KeyParameter(Hex.Decode("3F3E3D3C3B3A393837363534333231302F2E2D2C2B2A292827262524232221201F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100")), Hex.Decode("7F7E7D7C7B7A797877767574737271706F6E6D6C6B6A696867666564636261605F5E5D5C5B5A595857565554535251504F4E4D4C4B4A49484746454443424140")), "5D5B3E3DE5BAA70E0A0684D458856CE759C6018D0B3F087FC1DAC101D380236DD934F2880B02D56A575BCA35A0CE4B0D9BA1F4A39C16CA7D80D59956630F09E54EC91E32B6830FE08323ED393F8028D150BF03CAD0629A5AFEEFF6E44257980618DB2F32B7B2B65B96E8451F1090829D2FFFC615CC1581E9221438DCEAD1FD12", "FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C4C3C2C1C0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0AFAEADACABAAA9A8A7A6A5A4A3A2A1A09F9E9D9C9B9A999897969594939291908F8E8D8C8B8A89888786858483828180"), + + //OFB mode + new BlockCipherVectorTest(23, new OfbBlockCipher(new Dstu7624Engine(128, 128), 128), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F")), Hex.Decode("101112131415161718191A1B1C1D1E1F")), "202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F", "A19E3E5E53BE8A07C9E0C01298FF832953205C661BD85A51F3A94113BC785CAB634B36E89A8FDD16A12E4467F5CC5A26"), + new BlockCipherVectorTest(24, new OfbBlockCipher(new Dstu7624Engine(128, 128), 128), new ParametersWithIV(new KeyParameter(Hex.Decode("0F0E0D0C0B0A09080706050403020100")), Hex.Decode("1F1E1D1C1B1A19181716151413121110")), "649A1EAAE160AF20F5B3EF2F58D66C1178B82E00D26F30689C8EC22E8E86E9CBB0BD4FFEE39EB13C2311276A906DD636", "4F4E4D4C4B4A494847464544434241403F3E3D3C3B3A393837363534333231302F2E2D2C2B2A29282726252423222120"), + new BlockCipherVectorTest(25, new OfbBlockCipher(new Dstu7624Engine(128, 256), 128), new ParametersWithIV(new KeyParameter(Hex.Decode("1F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100")), Hex.Decode("2F2E2D2C2B2A29282726252423222120")), "1A66CFBFEC00C6D52E39923E858DD64B214AB787798D3D5059A6B498AD66B34EAC48C4074BEC0D98C6", "5F5E5D5C5B5A595857565554535251504F4E4D4C4B4A494847464544434241403F3E3D3C3B3A393837"), + new BlockCipherVectorTest(26, new OfbBlockCipher(new Dstu7624Engine(256, 256), 256), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F")), Hex.Decode("202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F")), "404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F90", "B62F7F144A8C6772E693A96890F064C3F06831BF743F5B0DD061067F3D22877331AA6A99D939F05B7550E9402BD1615CC7B2D4A167E83EC0D8A894F92C72E176F3880B61C311D69CE1210C59184E818E19"), + new BlockCipherVectorTest(27, new OfbBlockCipher(new Dstu7624Engine(256, 256), 256), new ParametersWithIV(new KeyParameter(Hex.Decode("1F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100")), Hex.Decode("3F3E3D3C3B3A393837363534333231302F2E2D2C2B2A29282726252423222120")), "7758A939DD6BD00CAF9153E5A5D5A66129105CA1EA54A97C06FA4A40960A068F55E34F9339A14436216948F92FA2FB5286D3AB1E81543FC0018A0C4E8C493475F4D35DCFB0A7A5377F6669B857CDC978E4", "9F9E9D9C9B9A999897969594939291908F8E8D8C8B8A898887868584838281807F7E7D7C7B7A797877767574737271706F6E6D6C6B6A696867666564636261605F5E5D5C5B5A595857565554535251504F"), + new BlockCipherVectorTest(28, new OfbBlockCipher(new Dstu7624Engine(256, 512), 256), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F")), Hex.Decode("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F")), "606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0", "0008F28A82D2D01D23BFB2F8BB4F06D8FE73BA4F48A2977585570ED3818323A668883C9DCFF610CC7E3EA5C025FBBC5CA6520F8F11CA35CEB9B07031E6DBFABE39001E9A3CC0A24BBC565939592B4DEDBD"), + new BlockCipherVectorTest(29, new OfbBlockCipher(new Dstu7624Engine(256, 512), 256), new ParametersWithIV(new KeyParameter(Hex.Decode("3F3E3D3C3B3A393837363534333231302F2E2D2C2B2A292827262524232221201F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100")), Hex.Decode("5F5E5D5C5B5A595857565554535251504F4E4D4C4B4A49484746454443424140")), "98E122708FDABB1B1A5765C396DC79D7573221EC486ADDABD1770B147A6DD00B5FBC4F1EC68C59775B7AAA4D43C4CCE4F396D982DF64D30B03EF6C3B997BA0ED940BBC590BD30D64B5AE207147D71086B5", "BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0AFAEADACABAAA9A8A7A6A5A4A3A2A1A09F9E9D9C9B9A999897969594939291908F8E8D8C8B8A898887868584838281807F7E7D7C7B7A797877767574737271706F"), + new BlockCipherVectorTest(30, new OfbBlockCipher(new Dstu7624Engine(512, 512), 512), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F")), Hex.Decode("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F")), "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0", "CAA761980599B3ED2E945C41891BAD95F72B11C73ED26536A6847458BC76C827357156B4B3FE0DC1877F5B9F17B866C37B21D89531DB48007D05DEC928B06766C014BB9080385EDF0677E48A0A39B5E7489E28E82FFFD1F84694F17296CB701656"), + new BlockCipherVectorTest(31, new OfbBlockCipher(new Dstu7624Engine(512, 512), 512), new ParametersWithIV(new KeyParameter(Hex.Decode("3F3E3D3C3B3A393837363534333231302F2E2D2C2B2A292827262524232221201F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100")), Hex.Decode("7F7E7D7C7B7A797877767574737271706F6E6D6C6B6A696867666564636261605F5E5D5C5B5A595857565554535251504F4E4D4C4B4A49484746454443424140")), "06C061A4A66DFC0910034B3CFBDC4206D8908241C56BF41C4103CFD6DF322210B87F57EAE9F9AD815E606A7D1E8E6BD7CB1EBFBDBCB085C2D06BF3CC1586CB2EE1D81D38437F425131321647E42F5DE309D33F25B89DE37124683E4B44824FC56D", "EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C4C3C2C1C0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0AFAEADACABAAA9A8A7A6A5A4A3A2A1A09F9E9D9C9B9A999897969594939291908F"), + + + + + + }; + + public override ITestResult Perform() + { + + ITestResult result = base.Perform(); + + result = MacTests(); //Mac tests + + result = KeyWrapTests(); //Key wrapping tests + + if (!result.IsSuccessful()) + { + return result; + } + else + { + return new SimpleTestResult(true, Name + ": Okay"); + } + + } + + private ITestResult MacTests() + { + /* + //MAC mode (PADDING NOT SUPPORTED) + //test 1 + byte[] key = Hex.Decode("000102030405060708090A0B0C0D0E0F"); + + byte[] authtext = Hex.Decode("202122232425262728292A2B2C2D2E2F" + + "303132333435363738393A3B3C3D3E3F" + + "404142434445464748494A4B4C4D4E4F"); + + byte[] expectedMac = Hex.Decode("123B4EAB8E63ECF3E645A99C1115E241"); + + byte[] mac = new byte[128 / 8]; + + Dstu7624Mac dstu7624Mac = new Dstu7624Mac(128, 128, 128); + dstu7624Mac.Init(new KeyParameter(key)); + dstu7624Mac.BlockUpdate(authtext, 0, authtext.Length); + dstu7624Mac.DoFinal(mac, 0); + + if (!Arrays.AreEqual(mac, expectedMac)) + { + return new SimpleTestResult(false, Name + ": Failed MAC test 1 - expected " + + Hex.ToHexString(expectedMac) + + " got " + Hex.ToHexString(mac)); + } + + + //test 2 + key = Hex.Decode("000102030405060708090A0B0C0D0E0F" + + "101112131415161718191A1B1C1D1E1F" + + "202122232425262728292A2B2C2D2E2F" + + "303132333435363738393A3B3C3D3E3F"); + + authtext = Hex.Decode("404142434445464748494A4B4C4D4E4F" + + "505152535455565758595A5B5C5D5E5F" + + "606162636465666768696A6B6C6D6E6F" + + "707172737475767778797A7B7C7D7E7F" + + "808182838485868788898A8B8C8D8E8F" + + "909192939495969798999A9B9C9D9E9F" + + "A0A1A2A3A4A5A6A7A8A9AAABACADAEAF" + + "B0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"); + + expectedMac = Hex.Decode("7279FA6BC8EF7525B2B35260D00A1743"); + + dstu7624Mac = new Dstu7624Mac(512, 512, 128); + dstu7624Mac.Init(new KeyParameter(key)); + dstu7624Mac.BlockUpdate(authtext, 0, authtext.Length); + dstu7624Mac.DoFinal(mac, 0); + + if (!Arrays.AreEqual(mac, expectedMac)) + { + return new SimpleTestResult(false, Name + ": Failed MAC test 2 - expected " + + Hex.ToHexString(expectedMac) + + " got " + Hex.ToHexString(mac)); + } + */ + return new SimpleTestResult(true, Name + ": Okay"); + } + private ITestResult KeyWrapTests() + { + //KW mode (PADDING NOT SUPPORTED) + //test 1 + byte[] key = Hex.Decode("000102030405060708090A0B0C0D0E0F"); + byte[] textToWrap = Hex.Decode("101112131415161718191A1B1C1D1E1F"); + byte[] expectedWrappedText = Hex.Decode("1DC91DC6E52575F6DBED25ADDA95A1B6AD3E15056E489738972C199FB9EE2913"); + + byte[] output = new byte[expectedWrappedText.Length]; + + Dstu7624WrapEngine wrapper = new Dstu7624WrapEngine(128, 128); + wrapper.Init(true, new KeyParameter(key)); + output = wrapper.Wrap(textToWrap, 0, textToWrap.Length); + + + if (!Arrays.AreEqual(output, expectedWrappedText)) + { + return new SimpleTestResult(false, Name + ": Failed KW (wrapping) test 1 - expected " + + Hex.ToHexString(expectedWrappedText) + + " got " + Hex.ToHexString(output)); + } + + + wrapper.Init(false, new KeyParameter(key)); + output = wrapper.Unwrap(expectedWrappedText, 0, expectedWrappedText.Length); + + if (!Arrays.AreEqual(output, textToWrap)) + { + return new SimpleTestResult(false, Name + ": Failed KW (unwrapping) test 1 - expected " + + Hex.ToHexString(textToWrap) + + " got " + Hex.ToHexString(output)); + } + + //test 2 + key = Hex.Decode("000102030405060708090A0B0C0D0E0F"); + textToWrap = Hex.Decode("101112131415161718191A1B1C1D1E1F20219000000000000000800000000000"); + expectedWrappedText = Hex.Decode("0EA983D6CE48484D51462C32CC61672210FCC44196ABE635BAF878FDB83E1A63114128585D49DB355C5819FD38039169"); + + output = new byte[expectedWrappedText.Length]; + + wrapper.Init(true, new KeyParameter(key)); + output = wrapper.Wrap(textToWrap, 0, textToWrap.Length); + + + if (!Arrays.AreEqual(output, expectedWrappedText)) + { + return new SimpleTestResult(false, Name + ": Failed KW (wrapping) test 2 - expected " + + Hex.ToHexString(expectedWrappedText) + + " got " + Hex.ToHexString(output)); + } + + + wrapper.Init(false, new KeyParameter(key)); + output = wrapper.Unwrap(expectedWrappedText, 0, expectedWrappedText.Length); + + if (!Arrays.AreEqual(output, textToWrap)) + { + return new SimpleTestResult(false, Name + ": Failed KW (unwrapping) test 2 - expected " + + Hex.ToHexString(textToWrap) + + " got " + Hex.ToHexString(output)); + } + + + //test 3 + key = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"); + textToWrap = Hex.Decode("202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F"); + expectedWrappedText = Hex.Decode("2D09A7C18E6A5A0816331EC27CEA596903F77EC8D63F3BDB73299DE7FD9F4558E05992B0B24B39E02EA496368E0841CC1E3FA44556A3048C5A6E9E335717D17D"); + + output = new byte[expectedWrappedText.Length]; + + wrapper = new Dstu7624WrapEngine(128, 256); + wrapper.Init(true, new KeyParameter(key)); + output = wrapper.Wrap(textToWrap, 0, textToWrap.Length); + + + if (!Arrays.AreEqual(output, expectedWrappedText)) + { + return new SimpleTestResult(false, Name + ": Failed KW (wrapping) test 3 - expected " + + Hex.ToHexString(expectedWrappedText) + + " got " + Hex.ToHexString(output)); + } + + wrapper.Init(false, new KeyParameter(key)); + output = wrapper.Unwrap(expectedWrappedText, 0, expectedWrappedText.Length); + + if (!Arrays.AreEqual(output, textToWrap)) + { + return new SimpleTestResult(false, Name + ": Failed KW (unwrapping) test 3 - expected " + + Hex.ToHexString(textToWrap) + + " got " + Hex.ToHexString(output)); + } + + //test 4 + key = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"); + textToWrap = Hex.Decode("202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464E8040000000000020"); + expectedWrappedText = Hex.Decode("37E3EECB91150C6FA04CFD19D6FC57B7168C9FA5C5ED18601C68EE4AFD7301F8C8C51D7A0A5CD34F6FAB0D8AF11845CC1E4B16E0489FDA1D76BA4EFCFD161F76"); + + output = new byte[expectedWrappedText.Length]; + + wrapper = new Dstu7624WrapEngine(128, 256); + wrapper.Init(true, new KeyParameter(key)); + output = wrapper.Wrap(textToWrap, 0, textToWrap.Length); + + + if (!Arrays.AreEqual(output, expectedWrappedText)) + { + return new SimpleTestResult(false, Name + ": Failed KW (wrapping) test 4 - expected " + + Hex.ToHexString(expectedWrappedText) + + " got " + Hex.ToHexString(output)); + } + + wrapper.Init(false, new KeyParameter(key)); + output = wrapper.Unwrap(expectedWrappedText, 0, expectedWrappedText.Length); + + if (!Arrays.AreEqual(output, textToWrap)) + { + return new SimpleTestResult(false, Name + ": Failed KW (unwrapping) test 4 - expected " + + Hex.ToHexString(textToWrap) + + " got " + Hex.ToHexString(output)); + } + + //test 5 + key = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"); + textToWrap = Hex.Decode("202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F"); + expectedWrappedText = Hex.Decode("BE59D3C3C31B2685A8FA57CD000727F16AF303F0D87BC2D7ABD80DC2796BBC4CDBC4E0408943AF4DAF7DE9084DC81BFEF15FDCDD0DF399983DF69BF730D7AE2A199CA4F878E4723B7171DD4D1E8DF59C0F25FA0C20946BA64F9037D724BB1D50B6C2BD9788B2AF83EF6163087CD2D4488BC19F3A858D813E3A8947A529B6D65D"); + + output = new byte[expectedWrappedText.Length]; + + wrapper = new Dstu7624WrapEngine(256, 256); + wrapper.Init(true, new KeyParameter(key)); + output = wrapper.Wrap(textToWrap, 0, textToWrap.Length); + + + if (!Arrays.AreEqual(output, expectedWrappedText)) + { + return new SimpleTestResult(false, Name + ": Failed KW (wrapping) test 5 - expected " + + Hex.ToHexString(expectedWrappedText) + + " got " + Hex.ToHexString(output)); + } + + wrapper.Init(false, new KeyParameter(key)); + output = wrapper.Unwrap(expectedWrappedText, 0, expectedWrappedText.Length); + + if (!Arrays.AreEqual(output, textToWrap)) + { + return new SimpleTestResult(false, Name + ": Failed KW (unwrapping) test 5 - expected " + + Hex.ToHexString(textToWrap) + + " got " + Hex.ToHexString(output)); + } + + + //test 6 + key = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"); + textToWrap = Hex.Decode("202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F708802000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000"); + expectedWrappedText = Hex.Decode("CC41D643B08592F509432E3C6F4B73156907A53B9FFB99B157DEC708F917AEA1E41D76475EDFB138A8B0220A152B673E9713DE7A2791E3573FE257C3FF3C0DAA9AD13477E52770F54CBF94D1603AED7CA876FB7913BC359D2B89562299FA92D32A9C17DBE4CC21CCE097089B9FBC245580D6DB59F8731D864B604E654397E5F5E7A79A6A777C75856039C8C86140D0CB359CA3923D902D08269F8D48E7F0F085"); + + output = new byte[expectedWrappedText.Length]; + + wrapper = new Dstu7624WrapEngine(256, 256); + wrapper.Init(true, new KeyParameter(key)); + output = wrapper.Wrap(textToWrap, 0, textToWrap.Length); + + + if (!Arrays.AreEqual(output, expectedWrappedText)) + { + return new SimpleTestResult(false, Name + ": Failed KW (wrapping) test 6 - expected " + + Hex.ToHexString(expectedWrappedText) + + " got " + Hex.ToHexString(output)); + } + + wrapper.Init(false, new KeyParameter(key)); + output = wrapper.Unwrap(expectedWrappedText, 0, expectedWrappedText.Length); + + if (!Arrays.AreEqual(output, textToWrap)) + { + return new SimpleTestResult(false, Name + ": Failed KW (unwrapping) test 6 - expected " + + Hex.ToHexString(textToWrap) + + " got " + Hex.ToHexString(output)); + } + + + //test 7 + key = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F"); + textToWrap = Hex.Decode("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F"); + expectedWrappedText = Hex.Decode("599217EB2B5270ECEF0BB716D70E251234A2451CE04FCFBAEEA92022C581F19B7C9386BB7476B4AD721D40778F49062C3605F1E8FAC9F3F3AC04E46E89E1844DBF4F18FA9303B288741ABD71013CF208F31B4C76FBE342F89B1ABFD97E830457555651B74D3CCDBF94CC5E5EEC22821536A96F44C8BC4346B0271303E67FD313"); + + output = new byte[expectedWrappedText.Length]; + + wrapper = new Dstu7624WrapEngine(256, 512); + wrapper.Init(true, new KeyParameter(key)); + output = wrapper.Wrap(textToWrap, 0, textToWrap.Length); + + + if (!Arrays.AreEqual(output, expectedWrappedText)) + { + return new SimpleTestResult(false, Name + ": Failed KW (wrapping) test 7 - expected " + + Hex.ToHexString(expectedWrappedText) + + " got " + Hex.ToHexString(output)); + } + + wrapper.Init(false, new KeyParameter(key)); + output = wrapper.Unwrap(expectedWrappedText, 0, expectedWrappedText.Length); + + if (!Arrays.AreEqual(output, textToWrap)) + { + return new SimpleTestResult(false, Name + ": Failed KW (unwrapping) test 7 - expected " + + Hex.ToHexString(textToWrap) + + " got " + Hex.ToHexString(output)); + } + + //test 8 + key = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F"); + textToWrap = Hex.Decode("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F908802000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000"); + expectedWrappedText = Hex.Decode("B92E58F53C38F7D23F1068FA98B921AC800AD0D1947BD620700D0B6088F87D03D6A516F54198154D0C71169C2BCF520F3DF3DF527FC23E800E9A65158D45BB253A3BD0493E4822DF0DB5A366BC2F47551C5D477DDDE724A0B869F562223CEDB9D4AA36C750FA864ADF938273FBC859F7D4930F6B70C6474304AB670BA32CB0C41023769338A29EA1555F526CDFEB75C72212CD2D29F4BA49C2A62ACBE4F3272B"); + + output = new byte[expectedWrappedText.Length]; + + wrapper = new Dstu7624WrapEngine(256, 512); + wrapper.Init(true, new KeyParameter(key)); + output = wrapper.Wrap(textToWrap, 0, textToWrap.Length); + + + if (!Arrays.AreEqual(output, expectedWrappedText)) + { + return new SimpleTestResult(false, Name + ": Failed KW (wrapping) test 8 - expected " + + Hex.ToHexString(expectedWrappedText) + + " got " + Hex.ToHexString(output)); + } + + wrapper.Init(false, new KeyParameter(key)); + output = wrapper.Unwrap(expectedWrappedText, 0, expectedWrappedText.Length); + + if (!Arrays.AreEqual(output, textToWrap)) + { + return new SimpleTestResult(false, Name + ": Failed KW (unwrapping) test 8 - expected " + + Hex.ToHexString(textToWrap) + + " got " + Hex.ToHexString(output)); + } + + //test 9 + key = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F"); + textToWrap = Hex.Decode("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"); + expectedWrappedText = Hex.Decode("9618AE6065069D5054464040F17337D58BEB51AE92391D740BDF7ABB239709C46270832039FF045BCF7878E7DA9C3B4CF89326CA8B4D29DB8680EEAE1B5A18463284713A323A69AEBF33CFC4B11283C7C8041FFC97668EDF727823411C9559816C108C11EC401643765527860D8DA0ED7254792C21DB775DEB1D6971C924CC83EB626173D894694943B1828ABDE8F9495BCEBA9AC3A4A03592C085AA29CC9A0C65786E631A702D589B819C89E79EEFF29C4EC312C8860BB68F02272EA770FB8D"); + + output = new byte[expectedWrappedText.Length]; + + wrapper = new Dstu7624WrapEngine(512, 512); + wrapper.Init(true, new KeyParameter(key)); + output = wrapper.Wrap(textToWrap, 0, textToWrap.Length); + + + if (!Arrays.AreEqual(output, expectedWrappedText)) + { + return new SimpleTestResult(false, Name + ": Failed KW (wrapping) test 9 - expected " + + Hex.ToHexString(expectedWrappedText) + + " got " + Hex.ToHexString(output)); + } + + wrapper.Init(false, new KeyParameter(key)); + output = wrapper.Unwrap(expectedWrappedText, 0, expectedWrappedText.Length); + + if (!Arrays.AreEqual(output, textToWrap)) + { + return new SimpleTestResult(false, Name + ": Failed KW (unwrapping) test 9 - expected " + + Hex.ToHexString(textToWrap) + + " got " + Hex.ToHexString(output)); + } + + + //test 10 + key = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F"); + textToWrap = Hex.Decode("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE00805000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); + expectedWrappedText = Hex.Decode("3A05BB41513555F171E9234D4834EDAD16C0BAA6136197650138219C5DA406A703C39259E9DCCF6F2691EC691CE7414B5D3CDA006DE6D6C62142FAAA742C5F8AF64FCE95BE7ABA7FE5E06C3C33EE67BAEAB196E3A71132CAE78CD605A22E34D53CD159217E7B692CC79FAC66BF5E08DBC4FE274299474E176DDDF9F462AC63F4872E9B7F16B98AA56707EE5F2F94616CFC6A9548ADBD7DCB73664C331213964593F712ECCDFA7A94E3ABA7995176EA4B7E77096A3A3FF4E4087F430B62D5DEE64999F235FA9EAC79896A1C2258BF1DFC8A6AD0E5E7E06EAEEA0CCC2DEF62F67ECE8D12EFF432277C40A7BF1A23440B3533AF1E2F7AE1BBC076D12628BB4BC7B2E4D4B4353BCEAF9A67276B3FA23CADCA80062B95EBB2D51510AFA16F97249DF98E7B845C9A410F24B3C8B3E838E58D22BC2D14F46190FC1BFDB60C9691404F99"); + + output = new byte[expectedWrappedText.Length]; + + wrapper = new Dstu7624WrapEngine(512, 512); + wrapper.Init(true, new KeyParameter(key)); + output = wrapper.Wrap(textToWrap, 0, textToWrap.Length); + + + if (!Arrays.AreEqual(output, expectedWrappedText)) + { + return new SimpleTestResult(false, Name + ": Failed KW (wrapping) test 10 - expected " + + Hex.ToHexString(expectedWrappedText) + + " got " + Hex.ToHexString(output)); + } + + wrapper.Init(false, new KeyParameter(key)); + output = wrapper.Unwrap(expectedWrappedText, 0, expectedWrappedText.Length); + + if (!Arrays.AreEqual(output, textToWrap)) + { + return new SimpleTestResult(false, Name + ": Failed KW (unwrapping) test 10 - expected " + + Hex.ToHexString(textToWrap) + + " got " + Hex.ToHexString(output)); + } + + return new SimpleTestResult(true, Name + ": Okay"); + } + + + [Test] + public void Dstu7624TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + + public override string Name + { + get { return "Dstu7624"; } + } + + public static void Main( + string[] args) + { + Dstu7624Test test = new Dstu7624Test(); + ITestResult result = test.Perform(); + + Console.WriteLine(result.ToString()); + } + } +} -- cgit 1.4.1 From 78381b39fea78957e121d33d21aa3c128ae04473 Mon Sep 17 00:00:00 2001 From: David Hook Date: Thu, 6 Jul 2017 15:09:38 +1000 Subject: DSTU 7624 MAC --- crypto/src/crypto/macs/DSTU7624Mac.cs | 160 ++++++++++++++++++++++++++++ crypto/test/src/crypto/test/DSTU7624Test.cs | 3 +- 2 files changed, 161 insertions(+), 2 deletions(-) create mode 100644 crypto/src/crypto/macs/DSTU7624Mac.cs (limited to 'crypto') diff --git a/crypto/src/crypto/macs/DSTU7624Mac.cs b/crypto/src/crypto/macs/DSTU7624Mac.cs new file mode 100644 index 000000000..a189e8638 --- /dev/null +++ b/crypto/src/crypto/macs/DSTU7624Mac.cs @@ -0,0 +1,160 @@ +using System; + +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; + + +namespace Org.BouncyCastle.Crypto.Macs +{ + /** + * implementation of DSTU 7624 MAC + */ + public class Dstu7624Mac : IMac + { + private int macSize; + + private Dstu7624Engine engine; + private int blockSize; + + private byte[] c, cTemp, kDelta; + private byte[] buf; + private int bufOff; + + public Dstu7624Mac(int blockSizeBits, int keySizeBits, int q) + { + engine = new Dstu7624Engine(blockSizeBits, keySizeBits); + + blockSize = blockSizeBits / 8; + + macSize = q / 8; + + c = new byte[blockSize]; + + cTemp = new byte[blockSize]; + + kDelta = new byte[blockSize]; + buf = new byte[blockSize]; + } + + public void Init(ICipherParameters parameters) + { + if (parameters is KeyParameter) + { + engine.Init(true, (KeyParameter)parameters); + + engine.ProcessBlock(kDelta, 0, kDelta, 0); + } + else + { + throw new ArgumentException("invalid parameter passed to Dstu7624Mac init - " + + Platform.GetTypeName(parameters)); + } + } + + public string AlgorithmName + { + get { return "Dstu7624Mac"; } + } + + public int GetMacSize() + { + return macSize; + } + + public void Update(byte input) + { + if (bufOff == buf.Length) + { + processBlock(buf, 0); + bufOff = 0; + } + + buf[bufOff++] = input; + } + + public void BlockUpdate(byte[] input, int inOff, int len) + { + if (len < 0) + { + throw new ArgumentException( + "Can't have a negative input length!"); + } + + int blockSize = engine.GetBlockSize(); + int gapLen = blockSize - bufOff; + + if (len > gapLen) + { + Array.Copy(input, inOff, buf, bufOff, gapLen); + + processBlock(buf, 0); + + bufOff = 0; + len -= gapLen; + inOff += gapLen; + + while (len > blockSize) + { + processBlock(input, inOff); + + len -= blockSize; + inOff += blockSize; + } + } + + Array.Copy(input, inOff, buf, bufOff, len); + + bufOff += len; + } + + private void processBlock(byte[] input, int inOff) + { + Xor(c, 0, input, inOff, cTemp); + + engine.ProcessBlock(cTemp, 0, c, 0); + } + + private void Xor(byte[] c, int cOff, byte[] input, int inOff, byte[] xorResult) + { + for (int byteIndex = 0; byteIndex < blockSize; byteIndex++) + { + xorResult[byteIndex] = (byte)(c[byteIndex + cOff] ^ input[byteIndex + inOff]); + } + } + + public int DoFinal(byte[] output, int outOff) + { + if (bufOff % buf.Length != 0) + { + throw new DataLengthException("Input must be a multiple of blocksize"); + } + + //Last block + Xor(c, 0, buf, 0, cTemp); + Xor(cTemp, 0, kDelta, 0, c); + engine.ProcessBlock(c, 0, c, 0); + + if (macSize + outOff > output.Length) + { + throw new DataLengthException("Output buffer too short"); + } + + Array.Copy(c, 0, output, outOff, macSize); + + return macSize; + } + + public void Reset() + { + Arrays.Fill(c, (byte)0x00); + Arrays.Fill(cTemp, (byte)0x00); + Arrays.Fill(kDelta, (byte)0x00); + Arrays.Fill(buf, (byte)0x00); + engine.Reset(); + engine.ProcessBlock(kDelta, 0, kDelta, 0); + bufOff = 0; + } + } +} diff --git a/crypto/test/src/crypto/test/DSTU7624Test.cs b/crypto/test/src/crypto/test/DSTU7624Test.cs index 5c06fd5d1..6d55146a4 100644 --- a/crypto/test/src/crypto/test/DSTU7624Test.cs +++ b/crypto/test/src/crypto/test/DSTU7624Test.cs @@ -97,7 +97,6 @@ namespace Org.BouncyCastle.Crypto.Tests private ITestResult MacTests() { - /* //MAC mode (PADDING NOT SUPPORTED) //test 1 byte[] key = Hex.Decode("000102030405060708090A0B0C0D0E0F"); @@ -151,7 +150,7 @@ namespace Org.BouncyCastle.Crypto.Tests + Hex.ToHexString(expectedMac) + " got " + Hex.ToHexString(mac)); } - */ + return new SimpleTestResult(true, Name + ": Okay"); } private ITestResult KeyWrapTests() -- cgit 1.4.1 From f83b8c09c6fe002c5fea009d8a9fb3e5c55856d1 Mon Sep 17 00:00:00 2001 From: David Hook Date: Thu, 6 Jul 2017 18:51:02 +1000 Subject: added KCTR --- crypto/src/crypto/modes/KCtrBlockCipher.cs | 235 +++++++++++++++++++++ crypto/test/src/crypto/test/DSTU7624Test.cs | 9 +- .../test/src/crypto/test/StreamCipherVectorTest.cs | 12 +- 3 files changed, 245 insertions(+), 11 deletions(-) create mode 100644 crypto/src/crypto/modes/KCtrBlockCipher.cs (limited to 'crypto') diff --git a/crypto/src/crypto/modes/KCtrBlockCipher.cs b/crypto/src/crypto/modes/KCtrBlockCipher.cs new file mode 100644 index 000000000..ff0249a6c --- /dev/null +++ b/crypto/src/crypto/modes/KCtrBlockCipher.cs @@ -0,0 +1,235 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Modes +{ + /** + * Implements a Gamming or Counter (CTR) mode on top of a DSTU 7624 block cipher. + */ + public class KCtrBlockCipher : IStreamCipher, IBlockCipher + { + private byte[] IV; + private byte[] ofbV; + private byte[] ofbOutV; + private bool initialised; + + private int byteCount; + + private readonly int blockSize; + private readonly IBlockCipher cipher; + + /** + * Basic constructor. + * + * @param cipher the block cipher to be used as the basis of the + * feedback mode. + */ + public KCtrBlockCipher(IBlockCipher cipher) + { + this.cipher = cipher; + this.IV = new byte[cipher.GetBlockSize()]; + this.blockSize = cipher.GetBlockSize(); + + this.ofbV = new byte[cipher.GetBlockSize()]; + this.ofbOutV = new byte[cipher.GetBlockSize()]; + } + + /** + * return the underlying block cipher that we are wrapping. + * + * @return the underlying block cipher that we are wrapping. + */ + public IBlockCipher GetUnderlyingCipher() + { + return cipher; + } + /** + * Initialise the cipher and, possibly, the initialisation vector (IV). + * If an IV isn't passed as part of the parameter, the IV will be all zeros. + * An IV which is too short is handled in FIPS compliant fashion. + * + * @param forEncryption if true the cipher is initialised for + * encryption, if false for decryption. + * @param param the key and other data required by the cipher. + * @exception ArgumentException if the parameters argument is + * inappropriate. + */ + public void Init( + bool forEncryption, + ICipherParameters parameters) + { + this.initialised = true; + if (parameters is ParametersWithIV) + { + ParametersWithIV ivParam = (ParametersWithIV)parameters; + byte[] iv = ivParam.GetIV(); + int diff = IV.Length - iv.Length; + + Array.Clear(IV, 0, IV.Length); + Array.Copy(iv, 0, IV, diff, iv.Length); + + parameters = ivParam.Parameters; + } + else + { + throw new ArgumentException("Invalid parameter passed"); + } + + // if it's null, key is to be reused. + if (parameters != null) + { + cipher.Init(true, parameters); + } + + Reset(); + } + + /** + * return the algorithm name and mode. + * + * @return the name of the underlying algorithm followed by "/KCTR" + * and the block size in bits. + */ + public string AlgorithmName + { + get { return cipher.AlgorithmName + "/KCTR"; } + } + + public bool IsPartialBlockOkay + { + get { return true; } + } + + /** + * return the block size we are operating at. + * + * @return the block size we are operating at (in bytes). + */ + public int GetBlockSize() + { + return cipher.GetBlockSize(); + } + + public byte ReturnByte(byte input) + { + return CalculateByte(input); + } + + public void ProcessBytes(byte[] input, int inOff, int len, byte[] output, int outOff) + { + if (outOff + len > output.Length) + { + throw new DataLengthException("Output buffer too short"); + } + + if (inOff + len > input.Length) + { + throw new DataLengthException("Input buffer too small"); + } + + int inStart = inOff; + int inEnd = inOff + len; + int outStart = outOff; + + while (inStart Date: Thu, 6 Jul 2017 19:51:10 +1000 Subject: refactored out key size --- crypto/src/crypto/engines/Dstu7624Engine.cs | 285 ++++++++++++------------ crypto/src/crypto/engines/Dstu7624WrapEngine.cs | 4 +- crypto/src/crypto/macs/DSTU7624Mac.cs | 4 +- crypto/src/crypto/util/Pack.cs | 9 + crypto/test/src/crypto/test/DSTU7624Test.cs | 68 +++--- 5 files changed, 186 insertions(+), 184 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/engines/Dstu7624Engine.cs b/crypto/src/crypto/engines/Dstu7624Engine.cs index 4699ee5bd..422b5574a 100644 --- a/crypto/src/crypto/engines/Dstu7624Engine.cs +++ b/crypto/src/crypto/engines/Dstu7624Engine.cs @@ -3,6 +3,7 @@ using System.Collections; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Crypto.Utilities; namespace Org.BouncyCastle.Crypto.Engines { @@ -12,133 +13,124 @@ namespace Org.BouncyCastle.Crypto.Engines public class Dstu7624Engine : IBlockCipher { - private const int BITS_IN_WORD = 64; - private const int BITS_IN_BYTE = 8; + private static readonly int BITS_IN_WORD = 64; + private static readonly int BITS_IN_BYTE = 8; - /* Block words size. */ - private const int kNB_128 = 2; - private const int kNB_256 = 4; - private const int kNB_512 = 8; + private static readonly int REDUCTION_POLYNOMIAL = 0x011d; /* x^8 + x^4 + x^3 + x^2 + 1 */ - /* Key words size. */ - private const int kNK_128 = 2; - private const int kNK_256 = 4; - private const int kNK_512 = 8; + private ulong[] internalState; + private ulong[] workingKey; + private ulong[][] roundKeys; - /* Block bits size. */ - private const int kBLOCK_128 = kNB_128 * BITS_IN_WORD; - private const int kBLOCK_256 = kNB_256 * BITS_IN_WORD; - private const int kBLOCK_512 = kNB_512 * BITS_IN_WORD; + /* Number of 64-bit words in block */ + private int wordsInBlock; - /* Block bits size. */ - private const int kKEY_128 = kNK_128 * BITS_IN_WORD; - private const int kKEY_256 = kNK_256 * BITS_IN_WORD; - private const int kKEY_512 = kNK_512 * BITS_IN_WORD; - - /* Number of enciphering rounds size depending on key length. */ - private const int kNR_128 = 10; - private const int kNR_256 = 14; - private const int kNR_512 = 18; - - private const int REDUCTION_POLYNOMIAL = 0x011d; /* x^8 + x^4 + x^3 + x^2 + 1 */ - - - private int nb; /* Number of 64-bit words in enciphering block. */ - private int nk; /*< Number of 64-bit words in key. */ - private int roundKeysAmount; /*< Number of enciphering rounds. */ - - private ulong[] internalState = null; /*< Current cipher state. */ - - - private ulong[] workingKey = null; - private ulong[][] roundKeys = null; /*< Round key computed from enciphering key. */ + /* Number of 64-bit words in key */ + private int wordsInKey; + /* Number of encryption rounds depending on key length */ + private static int ROUNDS_128 = 10; + private static int ROUNDS_256 = 14; + private static int ROUNDS_512 = 18; private int blockSizeBits; - private int keySizeBits; + private int roundsAmount; private bool forEncryption; + private byte[] internalStateBytes; + private byte[] tempInternalStateBytes; - public Dstu7624Engine(int blockSizeBits, int keySizeBits) + public Dstu7624Engine(int blockSizeBits) { - this.blockSizeBits = blockSizeBits; - this.keySizeBits = keySizeBits; - - if (blockSizeBits == kBLOCK_128) + /* DSTU7624 supports 128 | 256 | 512 key/block sizes */ + if (blockSizeBits != 128 && blockSizeBits != 256 && blockSizeBits != 512) { - nb = kBLOCK_128 / BITS_IN_WORD; - if (keySizeBits == kKEY_128) - { - nk = kKEY_128 / BITS_IN_WORD; - roundKeysAmount = kNR_128; - } - else if (keySizeBits == kKEY_256) - { - nk = kKEY_256 / BITS_IN_WORD; - roundKeysAmount = kNR_256; - } - else - { - throw new ArgumentException("Unsupported key size"); - } + throw new ArgumentException("Unsupported block length: only 128/256/512 are allowed"); } - else if (blockSizeBits == 256) + this.blockSizeBits = blockSizeBits; + + wordsInBlock = blockSizeBits / BITS_IN_WORD; + internalState = new ulong[wordsInBlock]; + + internalStateBytes = new byte[internalState.Length * 64 / BITS_IN_BYTE]; + tempInternalStateBytes = new byte[internalState.Length * 64 / BITS_IN_BYTE]; + } + + #region INITIALIZATION + public virtual void Init(bool forEncryption, ICipherParameters parameters) + { + if (parameters is KeyParameter) { - nb = kBLOCK_256 / BITS_IN_WORD; - if (keySizeBits == kKEY_256) + this.forEncryption = forEncryption; + + byte[] keyBytes = ((KeyParameter)parameters).GetKey(); + int keyBitLength = keyBytes.Length * BITS_IN_BYTE; + int blockBitLength = wordsInBlock * BITS_IN_WORD; + + if (keyBitLength != 128 && keyBitLength != 256 && keyBitLength != 512) { - nk = kKEY_256 / BITS_IN_WORD; - roundKeysAmount = kNR_256; + throw new ArgumentException("unsupported key length: only 128/256/512 are allowed"); } - else if (keySizeBits == kKEY_512) + + /* Limitations on key lengths depending on block lengths. See table 6.1 in standard */ + if (blockBitLength == 128) { - nk = kKEY_512 / BITS_IN_WORD; - roundKeysAmount = kNR_512; + if (keyBitLength == 512) + { + throw new ArgumentException("Unsupported key length"); + } } - else + + if (blockBitLength == 256) { - throw new ArgumentException("Unsupported key size"); + if (keyBitLength == 128) + { + throw new ArgumentException("Unsupported key length"); + } } - } - else if (blockSizeBits == kBLOCK_512) - { - nb = kBLOCK_512 / BITS_IN_WORD; - if (keySizeBits == kKEY_512) + + if (blockBitLength == 512) { - nk = kKEY_512 / BITS_IN_WORD; - roundKeysAmount = kNR_512; + if (keyBitLength != 512) + { + throw new ArgumentException("Unsupported key length"); + } } - else + + switch (keyBitLength) { - throw new ArgumentException("Unsupported key size"); + case 128: + roundsAmount = ROUNDS_128; + break; + case 256: + roundsAmount = ROUNDS_256; + break; + case 512: + roundsAmount = ROUNDS_512; + break; } - } - else - { - throw new ArgumentException("Unsupported block size"); - } - internalState = new ulong[nb]; + wordsInKey = keyBitLength / BITS_IN_WORD; - roundKeys = new ulong[roundKeysAmount + 1][]; - - for (int i = 0; i < roundKeysAmount + 1; i++) - { - roundKeys[i] = new ulong[nb]; - } - } + /* +1 round key as defined in standard */ + roundKeys = new ulong[roundsAmount + 1][]; + for (int roundKeyIndex = 0; roundKeyIndex < roundKeys.Length; roundKeyIndex++) + { + roundKeys[roundKeyIndex] = new ulong[wordsInBlock]; + } + workingKey = new ulong[wordsInKey]; + if (keyBytes.Length != wordsInKey * BITS_IN_WORD / BITS_IN_BYTE) + { + throw new ArgumentException("Invalid key parameter passed to DSTU7624Engine init"); + } - #region INITIALIZATION - public virtual void Init(bool forEncryption, ICipherParameters parameters) - { - if (parameters is KeyParameter) - { - workingKey = BytesToWords(((KeyParameter)parameters).GetKey()); + /* Unpack encryption key bytes to words */ + Pack.LE_To_UInt64(keyBytes, 0, workingKey); - ulong[] kt = new ulong[nb]; + ulong[] kt = new ulong[wordsInBlock]; KeyExpandKT(workingKey, kt); @@ -158,21 +150,21 @@ namespace Org.BouncyCastle.Crypto.Engines private void KeyExpandKT(ulong[] key, ulong[] kt) { - ulong[] k0 = new ulong[nb]; - ulong[] k1 = new ulong[nb]; + ulong[] k0 = new ulong[wordsInBlock]; + ulong[] k1 = new ulong[wordsInBlock]; - internalState = new ulong[nb]; - internalState[0] += (ulong)(nb + nk + 1); + internalState = new ulong[wordsInBlock]; + internalState[0] += (ulong)(wordsInBlock + wordsInKey + 1); - if (nb == nk) + if (wordsInBlock == wordsInKey) { Array.Copy(key, k0, k0.Length); Array.Copy(key, k1, k1.Length); } else { - Array.Copy(key, 0, k0, 0, nb); - Array.Copy(key, nb, k1, 0, nb); + Array.Copy(key, 0, k0, 0, wordsInBlock); + Array.Copy(key, wordsInBlock, k1, 0, wordsInBlock); } AddRoundKeyExpand(k0); @@ -187,33 +179,34 @@ namespace Org.BouncyCastle.Crypto.Engines EncryptionRound(); - Array.Copy(internalState, kt, nb); + Array.Copy(internalState, kt, wordsInBlock); } + private void KeyExpandEven(ulong[] key, ulong[] kt) { - ulong[] initial_data = new ulong[nk]; + ulong[] initial_data = new ulong[wordsInKey]; - ulong[] kt_round = new ulong[nb]; + ulong[] kt_round = new ulong[wordsInBlock]; - ulong[] tmv = new ulong[nb]; + ulong[] tmv = new ulong[wordsInBlock]; int round = 0; - Array.Copy(key, initial_data, nk); + Array.Copy(key, initial_data, wordsInKey); - for (int i = 0; i < nb; i++) + for (int i = 0; i < wordsInBlock; i++) { tmv[i] = 0x0001000100010001; } while (true) { - Array.Copy(kt, internalState, nb); + Array.Copy(kt, internalState, wordsInBlock); AddRoundKeyExpand(tmv); - Array.Copy(internalState, kt_round, nb); - Array.Copy(initial_data, internalState, nb); + Array.Copy(internalState, kt_round, wordsInBlock); + Array.Copy(initial_data, internalState, wordsInBlock); AddRoundKeyExpand(kt_round); @@ -225,24 +218,24 @@ namespace Org.BouncyCastle.Crypto.Engines AddRoundKeyExpand(kt_round); - Array.Copy(internalState, roundKeys[round], nb); + Array.Copy(internalState, roundKeys[round], wordsInBlock); - if (roundKeysAmount == round) + if (roundsAmount == round) { break; } - if (nk != nb) + if (wordsInKey != wordsInBlock) { round += 2; ShiftLeft(tmv); - Array.Copy(kt, internalState, nb); + Array.Copy(kt, internalState, wordsInBlock); AddRoundKeyExpand(tmv); - Array.Copy(internalState, kt_round, nb); - Array.Copy(initial_data, nb, internalState, 0, nb); + Array.Copy(internalState, kt_round, wordsInBlock); + Array.Copy(initial_data, wordsInBlock, internalState, 0, wordsInBlock); AddRoundKeyExpand(kt_round); @@ -254,9 +247,9 @@ namespace Org.BouncyCastle.Crypto.Engines AddRoundKeyExpand(kt_round); - Array.Copy(internalState, roundKeys[round], nb); + Array.Copy(internalState, roundKeys[round], wordsInBlock); - if (roundKeysAmount == round) + if (roundsAmount == round) { break; } @@ -273,9 +266,9 @@ namespace Org.BouncyCastle.Crypto.Engines } private void KeyExpandOdd() { - for (int i = 1; i < roundKeysAmount; i += 2) + for (int i = 1; i < roundsAmount; i += 2) { - Array.Copy(roundKeys[i - 1], roundKeys[i], nb); + Array.Copy(roundKeys[i - 1], roundKeys[i], wordsInBlock); RotateLeft(roundKeys[i]); } } @@ -311,11 +304,11 @@ namespace Org.BouncyCastle.Crypto.Engines ulong[] plain_ = BytesToWords(plain); - Array.Copy(plain_, internalState, nb); + Array.Copy(plain_, internalState, wordsInBlock); AddRoundKey(round); - for (round = 1; round < roundKeysAmount; round++) + for (round = 1; round < roundsAmount; round++) { EncryptionRound(); @@ -324,11 +317,11 @@ namespace Org.BouncyCastle.Crypto.Engines } EncryptionRound(); - AddRoundKey(roundKeysAmount); + AddRoundKey(roundsAmount); ulong[] cipherText_ = new ulong[internalState.Length]; - Array.Copy(internalState, cipherText_, nb); + Array.Copy(internalState, cipherText_, wordsInBlock); byte[] temp = WordsToBytes(cipherText_); @@ -340,15 +333,15 @@ namespace Org.BouncyCastle.Crypto.Engines Array.Copy(cipherText, inOff, cipherText, 0, blockSizeBits / BITS_IN_BYTE); Array.Resize(ref cipherText, blockSizeBits / BITS_IN_BYTE); - int round = roundKeysAmount; + int round = roundsAmount; ulong[] cipherText_ = BytesToWords(cipherText); - Array.Copy(cipherText_, internalState, nb); + Array.Copy(cipherText_, internalState, wordsInBlock); SubRoundKey(round); - for (round = roundKeysAmount - 1; round > 0; round--) + for (round = roundsAmount - 1; round > 0; round--) { DecryptionRound(); XorRoundKey(round); @@ -359,7 +352,7 @@ namespace Org.BouncyCastle.Crypto.Engines ulong[] decryptedText_ = new ulong[internalState.Length]; - Array.Copy(internalState, decryptedText_, nb); + Array.Copy(internalState, decryptedText_, wordsInBlock); byte[] temp = WordsToBytes(decryptedText_); @@ -378,7 +371,7 @@ namespace Org.BouncyCastle.Crypto.Engines private void AddRoundKeyExpand(ulong[] value) { - for (int i = 0; i < nb; i++) + for (int i = 0; i < wordsInBlock; i++) { internalState[i] += value[i]; } @@ -428,7 +421,7 @@ namespace Org.BouncyCastle.Crypto.Engines private void XorRoundKeyExpand(ulong[] value) { - for (int i = 0; i < nb; i++) + for (int i = 0; i < wordsInBlock; i++) { internalState[i] ^= value[i]; } @@ -436,7 +429,7 @@ namespace Org.BouncyCastle.Crypto.Engines private void XorRoundKey(int round) { - for (int i = 0; i < nb; i++) + for (int i = 0; i < wordsInBlock; i++) { internalState[i] ^= roundKeys[round][i]; } @@ -449,18 +442,18 @@ namespace Org.BouncyCastle.Crypto.Engines byte[] stateBytes = WordsToBytes(internalState); - byte[] nstate = new byte[nb * sizeof(ulong)]; + byte[] nstate = new byte[wordsInBlock * sizeof(ulong)]; for (row = 0; row < sizeof(ulong); row++) { - if (row % (sizeof(ulong) / nb) == 0) + if (row % (sizeof(ulong) / wordsInBlock) == 0) { shift += 1; } - for (col = 0; col < nb; col++) + for (col = 0; col < wordsInBlock; col++) { - nstate[row + ((col + shift) % nb) * sizeof(ulong)] = stateBytes[row + col * sizeof(ulong)]; + nstate[row + ((col + shift) % wordsInBlock) * sizeof(ulong)] = stateBytes[row + col * sizeof(ulong)]; } } @@ -474,18 +467,18 @@ namespace Org.BouncyCastle.Crypto.Engines int shift = -1; byte[] stateBytes = WordsToBytes(internalState); - byte[] nstate = new byte[nb * sizeof(ulong)]; + byte[] nstate = new byte[wordsInBlock * sizeof(ulong)]; for (row = 0; row < sizeof(ulong); row++) { - if (row % (sizeof(ulong) / nb) == 0) + if (row % (sizeof(ulong) / wordsInBlock) == 0) { shift += 1; } - for (col = 0; col < nb; col++) + for (col = 0; col < wordsInBlock; col++) { - nstate[row + col * sizeof(ulong)] = stateBytes[row + ((col + shift) % nb) * sizeof(ulong)]; + nstate[row + col * sizeof(ulong)] = stateBytes[row + ((col + shift) % wordsInBlock) * sizeof(ulong)]; } } @@ -537,7 +530,7 @@ namespace Org.BouncyCastle.Crypto.Engines private void AddRoundKey(int round) { - for (int i = 0; i < nb; ++i) + for (int i = 0; i < wordsInBlock; ++i) { internalState[i] += roundKeys[round][i]; } @@ -545,7 +538,7 @@ namespace Org.BouncyCastle.Crypto.Engines private void SubRoundKey(int round) { - for (int i = 0; i < nb; ++i) + for (int i = 0; i < wordsInBlock; ++i) { internalState[i] -= roundKeys[round][i]; } @@ -568,7 +561,7 @@ namespace Org.BouncyCastle.Crypto.Engines ulong result; byte[] stateBytes = WordsToBytes(internalState); - for (col = 0; col < nb; ++col) + for (col = 0; col < wordsInBlock; ++col) { result = 0; for (row = sizeof(ulong) - 1; row >= 0; --row) @@ -611,7 +604,7 @@ namespace Org.BouncyCastle.Crypto.Engines private void SubBytes() { - for (int i = 0; i < nb; i++) + for (int i = 0; i < wordsInBlock; i++) { internalState[i] = sboxesForEncryption[0][internalState[i] & 0x00000000000000FF] | ((ulong)sboxesForEncryption[1][(internalState[i] & 0x000000000000FF00) >> 8] << 8) | @@ -626,7 +619,7 @@ namespace Org.BouncyCastle.Crypto.Engines private void InvSubBytes() { - for (int i = 0; i < nb; i++) + for (int i = 0; i < wordsInBlock; i++) { internalState[i] = sboxesForDecryption[0][internalState[i] & 0x00000000000000FF] | ((ulong)sboxesForDecryption[1][(internalState[i] & 0x000000000000FF00) >> 8] << 8) | diff --git a/crypto/src/crypto/engines/Dstu7624WrapEngine.cs b/crypto/src/crypto/engines/Dstu7624WrapEngine.cs index bfe8d9c1c..5d21f6e85 100644 --- a/crypto/src/crypto/engines/Dstu7624WrapEngine.cs +++ b/crypto/src/crypto/engines/Dstu7624WrapEngine.cs @@ -21,9 +21,9 @@ namespace Org.BouncyCastle.Crypto.Engines private readonly byte[] checkSumArray, zeroArray; - public Dstu7624WrapEngine(int blockSizeBits, int keySizeBits) + public Dstu7624WrapEngine(int blockSizeBits) { - engine = new Dstu7624Engine(blockSizeBits, keySizeBits); + engine = new Dstu7624Engine(blockSizeBits); param = null; blockSize = blockSizeBits / 8; diff --git a/crypto/src/crypto/macs/DSTU7624Mac.cs b/crypto/src/crypto/macs/DSTU7624Mac.cs index a189e8638..953d8164f 100644 --- a/crypto/src/crypto/macs/DSTU7624Mac.cs +++ b/crypto/src/crypto/macs/DSTU7624Mac.cs @@ -22,9 +22,9 @@ namespace Org.BouncyCastle.Crypto.Macs private byte[] buf; private int bufOff; - public Dstu7624Mac(int blockSizeBits, int keySizeBits, int q) + public Dstu7624Mac(int blockSizeBits, int q) { - engine = new Dstu7624Engine(blockSizeBits, keySizeBits); + engine = new Dstu7624Engine(blockSizeBits); blockSize = blockSizeBits / 8; diff --git a/crypto/src/crypto/util/Pack.cs b/crypto/src/crypto/util/Pack.cs index 96f293d72..ebe5b7af1 100644 --- a/crypto/src/crypto/util/Pack.cs +++ b/crypto/src/crypto/util/Pack.cs @@ -298,5 +298,14 @@ namespace Org.BouncyCastle.Crypto.Utilities uint hi = LE_To_UInt32(bs, off + 4); return ((ulong)hi << 32) | (ulong)lo; } + + internal static void LE_To_UInt64(byte[] bs, int off, ulong[] ns) + { + for (int i = 0; i < ns.Length; ++i) + { + ns[i] = LE_To_UInt64(bs, off); + off += 8; + } + } } } diff --git a/crypto/test/src/crypto/test/DSTU7624Test.cs b/crypto/test/src/crypto/test/DSTU7624Test.cs index baced41fd..67dcd4420 100644 --- a/crypto/test/src/crypto/test/DSTU7624Test.cs +++ b/crypto/test/src/crypto/test/DSTU7624Test.cs @@ -19,7 +19,7 @@ namespace Org.BouncyCastle.Crypto.Tests public class Dstu7624Test : CipherTest { public Dstu7624Test() - : base(tests, new Dstu7624Engine(256, 256), new KeyParameter(new byte[32])) { } + : base(tests, new Dstu7624Engine(256), new KeyParameter(new byte[32])) { } @@ -48,32 +48,32 @@ namespace Org.BouncyCastle.Crypto.Tests new KBlockCipherVectorTest(13, new KCfbBlockCipher(new Dstu7624Engine(512, 512), 512), new ParametersWithIV(new KeyParameter(Hex.Decode("3F3E3D3C3B3A393837363534333231302F2E2D2C2B2A292827262524232221201F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100")), Hex.Decode("7F7E7D7C7B7A797877767574737271706F6E6D6C6B6A696867666564636261605F5E5D5C5B5A595857565554535251504F4E4D4C4B4A49484746454443424140")), "06C061A4A66DFC0910034B3CFBDC4206D8908241C56BF41C4103CFD6DF322210B87F57EAE9F9AD815E606a7D1E8E6BD7CB1EBFBDBCB085C2D06BF3CC1586CB2E88C9155E95B4872D86B49D80F5745B605EAF488AA520A717A92F4D68838E42C995", "EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C4C3C2C1C0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0AFAEADACABAAA9A8A7A6A5A4A3A2A1A09F9E9D9C9B9A999897969594939291908F"), */ //CBC mode (PADDING NOT SUPPORTED) - new BlockCipherVectorTest(14, new CbcBlockCipher(new Dstu7624Engine(128, 128)), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F")), Hex.Decode("101112131415161718191A1B1C1D1E1F")), "202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F", "A73625D7BE994E85469A9FAABCEDAAB6DBC5F65DD77BB35E06BD7D1D8EAFC8624D6CB31CE189C82B8979F2936DE9BF14"), - new BlockCipherVectorTest(15, new CbcBlockCipher(new Dstu7624Engine(128, 128)), new ParametersWithIV(new KeyParameter(Hex.Decode("0F0E0D0C0B0A09080706050403020100")), Hex.Decode("1F1E1D1C1B1A19181716151413121110")), "88F2F048BA696170E3818915E0DBC0AFA6F141FEBC2F817138DA4AAB2DBF9CE490A488C9C82AC83FB0A6C0EEB64CFD22", "4F4E4D4C4B4A494847464544434241403F3E3D3C3B3A393837363534333231302F2E2D2C2B2A29282726252423222120"), - new BlockCipherVectorTest(16, new CbcBlockCipher(new Dstu7624Engine(128, 256)), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F")), Hex.Decode("202122232425262728292A2B2C2D2E2F")), "303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D8000", "13EA15843AD14C50BC03ECEF1F43E398E4217752D3EB046AC393DACC5CA1D6FA0EB9FCEB229362B4F1565527EE3D8433"), - new BlockCipherVectorTest(17, new CbcBlockCipher(new Dstu7624Engine(128, 256)), new ParametersWithIV(new KeyParameter(Hex.Decode("1F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100")), Hex.Decode("2F2E2D2C2B2A29282726252423222120")), "BC8F026FC603ECE05C24FDE87542730999B381870882AC0535D4368C4BABD81B884E96E853EE7E055262D9D204FBE212", "5F5E5D5C5B5A595857565554535251504F4E4D4C4B4A494847464544434241403F3E3D3C3B3A39383736353433323130"), - new BlockCipherVectorTest(18, new CbcBlockCipher(new Dstu7624Engine(256, 256)), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F")), Hex.Decode("202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F")), "404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F", "9CDFDAA75929E7C2A5CFC1BF16B42C5AE3886D0258E8C577DC01DAF62D185FB999B9867736B87110F5F1BC7481912C593F48FF79E2AFDFAB9F704A277EC3E557B1B0A9F223DAE6ED5AF591C4F2D6FB22E48334F5E9B96B1A2EA5200F30A406CE"), - new BlockCipherVectorTest(19, new CbcBlockCipher(new Dstu7624Engine(256, 512)), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F")), Hex.Decode("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F")), "606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF", "B8A2474578C2FEBF3F94703587BD5FDC3F4A4D2F43575B6144A1E1031FB3D1452B7FD52F5E3411461DAC506869FF8D2FAEF4FEE60379AE00B33AA3EAF911645AF8091CD8A45D141D1FB150E5A01C1F26FF3DBD26AC4225EC7577B2CE57A5B0FF"), - new BlockCipherVectorTest(20, new CbcBlockCipher(new Dstu7624Engine(256, 512)), new ParametersWithIV(new KeyParameter(Hex.Decode("3F3E3D3C3B3A393837363534333231302F2E2D2C2B2A292827262524232221201F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100")), Hex.Decode("5F5E5D5C5B5A595857565554535251504F4E4D4C4B4A49484746454443424140")), "C69A59E10D00F087319B62288A57417C074EAD07C732A87055F0A5AD2BB288105705C45E091A9A6726E9672DC7D8C76FC45C782BCFEF7C39D94DEB84B17035BC8651255A0D34373451B6E1A2C827DB97566C9FF5506C5579F982A0EFC5BA7C28", "BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0AFAEADACABAAA9A8A7A6A5A4A3A2A1A09F9E9D9C9B9A999897969594939291908F8E8D8C8B8A898887868584838281807F7E7D7C7B7A797877767574737271706F6E6D6C6B6A69686766656463626160"), - new BlockCipherVectorTest(21, new CbcBlockCipher(new Dstu7624Engine(512, 512)), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F")), Hex.Decode("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F")), "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF", "D4739B829EF901B24C1162AE4FDEF897EDA41FAC7F5770CDC90E1D1CDF124E8D7831E06B4498A4B6F6EC815DF2461DC99BB0449B0F09FCAA2C84090534BCC9329626FD74EF8F0A0BCB5765184629C3CBF53B0FB134F6D0421174B1C4E884D1CD1069A7AD19752DCEBF655842E79B7858BDE01390A760D85E88925BFE38B0FA57"), - new BlockCipherVectorTest(22, new CbcBlockCipher(new Dstu7624Engine(512, 512)), new ParametersWithIV(new KeyParameter(Hex.Decode("3F3E3D3C3B3A393837363534333231302F2E2D2C2B2A292827262524232221201F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100")), Hex.Decode("7F7E7D7C7B7A797877767574737271706F6E6D6C6B6A696867666564636261605F5E5D5C5B5A595857565554535251504F4E4D4C4B4A49484746454443424140")), "5D5B3E3DE5BAA70E0A0684D458856CE759C6018D0B3F087FC1DAC101D380236DD934F2880B02D56A575BCA35A0CE4B0D9BA1F4A39C16CA7D80D59956630F09E54EC91E32B6830FE08323ED393F8028D150BF03CAD0629A5AFEEFF6E44257980618DB2F32B7B2B65B96E8451F1090829D2FFFC615CC1581E9221438DCEAD1FD12", "FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C4C3C2C1C0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0AFAEADACABAAA9A8A7A6A5A4A3A2A1A09F9E9D9C9B9A999897969594939291908F8E8D8C8B8A89888786858483828180"), + new BlockCipherVectorTest(14, new CbcBlockCipher(new Dstu7624Engine(128)), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F")), Hex.Decode("101112131415161718191A1B1C1D1E1F")), "202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F", "A73625D7BE994E85469A9FAABCEDAAB6DBC5F65DD77BB35E06BD7D1D8EAFC8624D6CB31CE189C82B8979F2936DE9BF14"), + new BlockCipherVectorTest(15, new CbcBlockCipher(new Dstu7624Engine(128)), new ParametersWithIV(new KeyParameter(Hex.Decode("0F0E0D0C0B0A09080706050403020100")), Hex.Decode("1F1E1D1C1B1A19181716151413121110")), "88F2F048BA696170E3818915E0DBC0AFA6F141FEBC2F817138DA4AAB2DBF9CE490A488C9C82AC83FB0A6C0EEB64CFD22", "4F4E4D4C4B4A494847464544434241403F3E3D3C3B3A393837363534333231302F2E2D2C2B2A29282726252423222120"), + new BlockCipherVectorTest(16, new CbcBlockCipher(new Dstu7624Engine(128)), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F")), Hex.Decode("202122232425262728292A2B2C2D2E2F")), "303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D8000", "13EA15843AD14C50BC03ECEF1F43E398E4217752D3EB046AC393DACC5CA1D6FA0EB9FCEB229362B4F1565527EE3D8433"), + new BlockCipherVectorTest(17, new CbcBlockCipher(new Dstu7624Engine(128)), new ParametersWithIV(new KeyParameter(Hex.Decode("1F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100")), Hex.Decode("2F2E2D2C2B2A29282726252423222120")), "BC8F026FC603ECE05C24FDE87542730999B381870882AC0535D4368C4BABD81B884E96E853EE7E055262D9D204FBE212", "5F5E5D5C5B5A595857565554535251504F4E4D4C4B4A494847464544434241403F3E3D3C3B3A39383736353433323130"), + new BlockCipherVectorTest(18, new CbcBlockCipher(new Dstu7624Engine(256)), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F")), Hex.Decode("202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F")), "404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F", "9CDFDAA75929E7C2A5CFC1BF16B42C5AE3886D0258E8C577DC01DAF62D185FB999B9867736B87110F5F1BC7481912C593F48FF79E2AFDFAB9F704A277EC3E557B1B0A9F223DAE6ED5AF591C4F2D6FB22E48334F5E9B96B1A2EA5200F30A406CE"), + new BlockCipherVectorTest(19, new CbcBlockCipher(new Dstu7624Engine(256)), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F")), Hex.Decode("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F")), "606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF", "B8A2474578C2FEBF3F94703587BD5FDC3F4A4D2F43575B6144A1E1031FB3D1452B7FD52F5E3411461DAC506869FF8D2FAEF4FEE60379AE00B33AA3EAF911645AF8091CD8A45D141D1FB150E5A01C1F26FF3DBD26AC4225EC7577B2CE57A5B0FF"), + new BlockCipherVectorTest(20, new CbcBlockCipher(new Dstu7624Engine(256)), new ParametersWithIV(new KeyParameter(Hex.Decode("3F3E3D3C3B3A393837363534333231302F2E2D2C2B2A292827262524232221201F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100")), Hex.Decode("5F5E5D5C5B5A595857565554535251504F4E4D4C4B4A49484746454443424140")), "C69A59E10D00F087319B62288A57417C074EAD07C732A87055F0A5AD2BB288105705C45E091A9A6726E9672DC7D8C76FC45C782BCFEF7C39D94DEB84B17035BC8651255A0D34373451B6E1A2C827DB97566C9FF5506C5579F982A0EFC5BA7C28", "BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0AFAEADACABAAA9A8A7A6A5A4A3A2A1A09F9E9D9C9B9A999897969594939291908F8E8D8C8B8A898887868584838281807F7E7D7C7B7A797877767574737271706F6E6D6C6B6A69686766656463626160"), + new BlockCipherVectorTest(21, new CbcBlockCipher(new Dstu7624Engine(512)), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F")), Hex.Decode("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F")), "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF", "D4739B829EF901B24C1162AE4FDEF897EDA41FAC7F5770CDC90E1D1CDF124E8D7831E06B4498A4B6F6EC815DF2461DC99BB0449B0F09FCAA2C84090534BCC9329626FD74EF8F0A0BCB5765184629C3CBF53B0FB134F6D0421174B1C4E884D1CD1069A7AD19752DCEBF655842E79B7858BDE01390A760D85E88925BFE38B0FA57"), + new BlockCipherVectorTest(22, new CbcBlockCipher(new Dstu7624Engine(512)), new ParametersWithIV(new KeyParameter(Hex.Decode("3F3E3D3C3B3A393837363534333231302F2E2D2C2B2A292827262524232221201F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100")), Hex.Decode("7F7E7D7C7B7A797877767574737271706F6E6D6C6B6A696867666564636261605F5E5D5C5B5A595857565554535251504F4E4D4C4B4A49484746454443424140")), "5D5B3E3DE5BAA70E0A0684D458856CE759C6018D0B3F087FC1DAC101D380236DD934F2880B02D56A575BCA35A0CE4B0D9BA1F4A39C16CA7D80D59956630F09E54EC91E32B6830FE08323ED393F8028D150BF03CAD0629A5AFEEFF6E44257980618DB2F32B7B2B65B96E8451F1090829D2FFFC615CC1581E9221438DCEAD1FD12", "FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C4C3C2C1C0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0AFAEADACABAAA9A8A7A6A5A4A3A2A1A09F9E9D9C9B9A999897969594939291908F8E8D8C8B8A89888786858483828180"), //OFB mode - new BlockCipherVectorTest(23, new OfbBlockCipher(new Dstu7624Engine(128, 128), 128), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F")), Hex.Decode("101112131415161718191A1B1C1D1E1F")), "202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F", "A19E3E5E53BE8A07C9E0C01298FF832953205C661BD85A51F3A94113BC785CAB634B36E89A8FDD16A12E4467F5CC5A26"), - new BlockCipherVectorTest(24, new OfbBlockCipher(new Dstu7624Engine(128, 128), 128), new ParametersWithIV(new KeyParameter(Hex.Decode("0F0E0D0C0B0A09080706050403020100")), Hex.Decode("1F1E1D1C1B1A19181716151413121110")), "649A1EAAE160AF20F5B3EF2F58D66C1178B82E00D26F30689C8EC22E8E86E9CBB0BD4FFEE39EB13C2311276A906DD636", "4F4E4D4C4B4A494847464544434241403F3E3D3C3B3A393837363534333231302F2E2D2C2B2A29282726252423222120"), - new BlockCipherVectorTest(25, new OfbBlockCipher(new Dstu7624Engine(128, 256), 128), new ParametersWithIV(new KeyParameter(Hex.Decode("1F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100")), Hex.Decode("2F2E2D2C2B2A29282726252423222120")), "1A66CFBFEC00C6D52E39923E858DD64B214AB787798D3D5059A6B498AD66B34EAC48C4074BEC0D98C6", "5F5E5D5C5B5A595857565554535251504F4E4D4C4B4A494847464544434241403F3E3D3C3B3A393837"), - new BlockCipherVectorTest(26, new OfbBlockCipher(new Dstu7624Engine(256, 256), 256), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F")), Hex.Decode("202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F")), "404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F90", "B62F7F144A8C6772E693A96890F064C3F06831BF743F5B0DD061067F3D22877331AA6A99D939F05B7550E9402BD1615CC7B2D4A167E83EC0D8A894F92C72E176F3880B61C311D69CE1210C59184E818E19"), - new BlockCipherVectorTest(27, new OfbBlockCipher(new Dstu7624Engine(256, 256), 256), new ParametersWithIV(new KeyParameter(Hex.Decode("1F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100")), Hex.Decode("3F3E3D3C3B3A393837363534333231302F2E2D2C2B2A29282726252423222120")), "7758A939DD6BD00CAF9153E5A5D5A66129105CA1EA54A97C06FA4A40960A068F55E34F9339A14436216948F92FA2FB5286D3AB1E81543FC0018A0C4E8C493475F4D35DCFB0A7A5377F6669B857CDC978E4", "9F9E9D9C9B9A999897969594939291908F8E8D8C8B8A898887868584838281807F7E7D7C7B7A797877767574737271706F6E6D6C6B6A696867666564636261605F5E5D5C5B5A595857565554535251504F"), - new BlockCipherVectorTest(28, new OfbBlockCipher(new Dstu7624Engine(256, 512), 256), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F")), Hex.Decode("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F")), "606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0", "0008F28A82D2D01D23BFB2F8BB4F06D8FE73BA4F48A2977585570ED3818323A668883C9DCFF610CC7E3EA5C025FBBC5CA6520F8F11CA35CEB9B07031E6DBFABE39001E9A3CC0A24BBC565939592B4DEDBD"), - new BlockCipherVectorTest(29, new OfbBlockCipher(new Dstu7624Engine(256, 512), 256), new ParametersWithIV(new KeyParameter(Hex.Decode("3F3E3D3C3B3A393837363534333231302F2E2D2C2B2A292827262524232221201F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100")), Hex.Decode("5F5E5D5C5B5A595857565554535251504F4E4D4C4B4A49484746454443424140")), "98E122708FDABB1B1A5765C396DC79D7573221EC486ADDABD1770B147A6DD00B5FBC4F1EC68C59775B7AAA4D43C4CCE4F396D982DF64D30B03EF6C3B997BA0ED940BBC590BD30D64B5AE207147D71086B5", "BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0AFAEADACABAAA9A8A7A6A5A4A3A2A1A09F9E9D9C9B9A999897969594939291908F8E8D8C8B8A898887868584838281807F7E7D7C7B7A797877767574737271706F"), - new BlockCipherVectorTest(30, new OfbBlockCipher(new Dstu7624Engine(512, 512), 512), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F")), Hex.Decode("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F")), "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0", "CAA761980599B3ED2E945C41891BAD95F72B11C73ED26536A6847458BC76C827357156B4B3FE0DC1877F5B9F17B866C37B21D89531DB48007D05DEC928B06766C014BB9080385EDF0677E48A0A39B5E7489E28E82FFFD1F84694F17296CB701656"), - new BlockCipherVectorTest(31, new OfbBlockCipher(new Dstu7624Engine(512, 512), 512), new ParametersWithIV(new KeyParameter(Hex.Decode("3F3E3D3C3B3A393837363534333231302F2E2D2C2B2A292827262524232221201F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100")), Hex.Decode("7F7E7D7C7B7A797877767574737271706F6E6D6C6B6A696867666564636261605F5E5D5C5B5A595857565554535251504F4E4D4C4B4A49484746454443424140")), "06C061A4A66DFC0910034B3CFBDC4206D8908241C56BF41C4103CFD6DF322210B87F57EAE9F9AD815E606A7D1E8E6BD7CB1EBFBDBCB085C2D06BF3CC1586CB2EE1D81D38437F425131321647E42F5DE309D33F25B89DE37124683E4B44824FC56D", "EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C4C3C2C1C0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0AFAEADACABAAA9A8A7A6A5A4A3A2A1A09F9E9D9C9B9A999897969594939291908F"), + new BlockCipherVectorTest(23, new OfbBlockCipher(new Dstu7624Engine(128), 128), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F")), Hex.Decode("101112131415161718191A1B1C1D1E1F")), "202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F", "A19E3E5E53BE8A07C9E0C01298FF832953205C661BD85A51F3A94113BC785CAB634B36E89A8FDD16A12E4467F5CC5A26"), + new BlockCipherVectorTest(24, new OfbBlockCipher(new Dstu7624Engine(128), 128), new ParametersWithIV(new KeyParameter(Hex.Decode("0F0E0D0C0B0A09080706050403020100")), Hex.Decode("1F1E1D1C1B1A19181716151413121110")), "649A1EAAE160AF20F5B3EF2F58D66C1178B82E00D26F30689C8EC22E8E86E9CBB0BD4FFEE39EB13C2311276A906DD636", "4F4E4D4C4B4A494847464544434241403F3E3D3C3B3A393837363534333231302F2E2D2C2B2A29282726252423222120"), + new BlockCipherVectorTest(25, new OfbBlockCipher(new Dstu7624Engine(128), 128), new ParametersWithIV(new KeyParameter(Hex.Decode("1F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100")), Hex.Decode("2F2E2D2C2B2A29282726252423222120")), "1A66CFBFEC00C6D52E39923E858DD64B214AB787798D3D5059A6B498AD66B34EAC48C4074BEC0D98C6", "5F5E5D5C5B5A595857565554535251504F4E4D4C4B4A494847464544434241403F3E3D3C3B3A393837"), + new BlockCipherVectorTest(26, new OfbBlockCipher(new Dstu7624Engine(256), 256), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F")), Hex.Decode("202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F")), "404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F90", "B62F7F144A8C6772E693A96890F064C3F06831BF743F5B0DD061067F3D22877331AA6A99D939F05B7550E9402BD1615CC7B2D4A167E83EC0D8A894F92C72E176F3880B61C311D69CE1210C59184E818E19"), + new BlockCipherVectorTest(27, new OfbBlockCipher(new Dstu7624Engine(256), 256), new ParametersWithIV(new KeyParameter(Hex.Decode("1F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100")), Hex.Decode("3F3E3D3C3B3A393837363534333231302F2E2D2C2B2A29282726252423222120")), "7758A939DD6BD00CAF9153E5A5D5A66129105CA1EA54A97C06FA4A40960A068F55E34F9339A14436216948F92FA2FB5286D3AB1E81543FC0018A0C4E8C493475F4D35DCFB0A7A5377F6669B857CDC978E4", "9F9E9D9C9B9A999897969594939291908F8E8D8C8B8A898887868584838281807F7E7D7C7B7A797877767574737271706F6E6D6C6B6A696867666564636261605F5E5D5C5B5A595857565554535251504F"), + new BlockCipherVectorTest(28, new OfbBlockCipher(new Dstu7624Engine(256), 256), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F")), Hex.Decode("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F")), "606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0", "0008F28A82D2D01D23BFB2F8BB4F06D8FE73BA4F48A2977585570ED3818323A668883C9DCFF610CC7E3EA5C025FBBC5CA6520F8F11CA35CEB9B07031E6DBFABE39001E9A3CC0A24BBC565939592B4DEDBD"), + new BlockCipherVectorTest(29, new OfbBlockCipher(new Dstu7624Engine(256), 256), new ParametersWithIV(new KeyParameter(Hex.Decode("3F3E3D3C3B3A393837363534333231302F2E2D2C2B2A292827262524232221201F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100")), Hex.Decode("5F5E5D5C5B5A595857565554535251504F4E4D4C4B4A49484746454443424140")), "98E122708FDABB1B1A5765C396DC79D7573221EC486ADDABD1770B147A6DD00B5FBC4F1EC68C59775B7AAA4D43C4CCE4F396D982DF64D30B03EF6C3B997BA0ED940BBC590BD30D64B5AE207147D71086B5", "BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0AFAEADACABAAA9A8A7A6A5A4A3A2A1A09F9E9D9C9B9A999897969594939291908F8E8D8C8B8A898887868584838281807F7E7D7C7B7A797877767574737271706F"), + new BlockCipherVectorTest(30, new OfbBlockCipher(new Dstu7624Engine(512), 512), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F")), Hex.Decode("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F")), "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0", "CAA761980599B3ED2E945C41891BAD95F72B11C73ED26536A6847458BC76C827357156B4B3FE0DC1877F5B9F17B866C37B21D89531DB48007D05DEC928B06766C014BB9080385EDF0677E48A0A39B5E7489E28E82FFFD1F84694F17296CB701656"), + new BlockCipherVectorTest(31, new OfbBlockCipher(new Dstu7624Engine(512), 512), new ParametersWithIV(new KeyParameter(Hex.Decode("3F3E3D3C3B3A393837363534333231302F2E2D2C2B2A292827262524232221201F1E1D1C1B1A191817161514131211100F0E0D0C0B0A09080706050403020100")), Hex.Decode("7F7E7D7C7B7A797877767574737271706F6E6D6C6B6A696867666564636261605F5E5D5C5B5A595857565554535251504F4E4D4C4B4A49484746454443424140")), "06C061A4A66DFC0910034B3CFBDC4206D8908241C56BF41C4103CFD6DF322210B87F57EAE9F9AD815E606A7D1E8E6BD7CB1EBFBDBCB085C2D06BF3CC1586CB2EE1D81D38437F425131321647E42F5DE309D33F25B89DE37124683E4B44824FC56D", "EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D5D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C5C4C3C2C1C0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0AFAEADACABAAA9A8A7A6A5A4A3A2A1A09F9E9D9C9B9A999897969594939291908F"), //CTR mode - new BlockCipherVectorTest(24, new KCtrBlockCipher(new Dstu7624Engine(128, 128)), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F")), Hex.Decode("101112131415161718191A1B1C1D1E1F")), "202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748", "A90A6B9780ABDFDFF64D14F5439E88F266DC50EDD341528DD5E698E2F000CE21F872DAF9FE1811844A"), - new BlockCipherVectorTest(25, new KCtrBlockCipher(new Dstu7624Engine(128, 128)), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F")), Hex.Decode("101112131415161718191A1B1C1D1E1F")), "303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F", "B91A7B8790BBCFCFE65D04E5538E98E216AC209DA33122FDA596E8928070BE51"), - new StreamCipherVectorTest(26, new KCtrBlockCipher(new Dstu7624Engine(128, 128)), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F")), Hex.Decode("101112131415161718191A1B1C1D1E1F")), "202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748", "A90A6B9780ABDFDFF64D14F5439E88F266DC50EDD341528DD5E698E2F000CE21F872DAF9FE1811844A"), - new StreamCipherVectorTest(27, new KCtrBlockCipher(new Dstu7624Engine(128, 128)), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F")), Hex.Decode("101112131415161718191A1B1C1D1E1F")), "303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F", "B91A7B8790BBCFCFE65D04E5538E98E216AC209DA33122FDA596E8928070BE51") + new BlockCipherVectorTest(24, new KCtrBlockCipher(new Dstu7624Engine(128)), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F")), Hex.Decode("101112131415161718191A1B1C1D1E1F")), "202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748", "A90A6B9780ABDFDFF64D14F5439E88F266DC50EDD341528DD5E698E2F000CE21F872DAF9FE1811844A"), + new BlockCipherVectorTest(25, new KCtrBlockCipher(new Dstu7624Engine(128)), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F")), Hex.Decode("101112131415161718191A1B1C1D1E1F")), "303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F", "B91A7B8790BBCFCFE65D04E5538E98E216AC209DA33122FDA596E8928070BE51"), + new StreamCipherVectorTest(26, new KCtrBlockCipher(new Dstu7624Engine(128)), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F")), Hex.Decode("101112131415161718191A1B1C1D1E1F")), "202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748", "A90A6B9780ABDFDFF64D14F5439E88F266DC50EDD341528DD5E698E2F000CE21F872DAF9FE1811844A"), + new StreamCipherVectorTest(27, new KCtrBlockCipher(new Dstu7624Engine(128)), new ParametersWithIV(new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F")), Hex.Decode("101112131415161718191A1B1C1D1E1F")), "303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F", "B91A7B8790BBCFCFE65D04E5538E98E216AC209DA33122FDA596E8928070BE51") }; public override ITestResult Perform() @@ -110,7 +110,7 @@ namespace Org.BouncyCastle.Crypto.Tests byte[] mac = new byte[128 / 8]; - Dstu7624Mac dstu7624Mac = new Dstu7624Mac(128, 128, 128); + Dstu7624Mac dstu7624Mac = new Dstu7624Mac(128, 128); dstu7624Mac.Init(new KeyParameter(key)); dstu7624Mac.BlockUpdate(authtext, 0, authtext.Length); dstu7624Mac.DoFinal(mac, 0); @@ -140,7 +140,7 @@ namespace Org.BouncyCastle.Crypto.Tests expectedMac = Hex.Decode("7279FA6BC8EF7525B2B35260D00A1743"); - dstu7624Mac = new Dstu7624Mac(512, 512, 128); + dstu7624Mac = new Dstu7624Mac(512, 128); dstu7624Mac.Init(new KeyParameter(key)); dstu7624Mac.BlockUpdate(authtext, 0, authtext.Length); dstu7624Mac.DoFinal(mac, 0); @@ -164,7 +164,7 @@ namespace Org.BouncyCastle.Crypto.Tests byte[] output = new byte[expectedWrappedText.Length]; - Dstu7624WrapEngine wrapper = new Dstu7624WrapEngine(128, 128); + Dstu7624WrapEngine wrapper = new Dstu7624WrapEngine(128); wrapper.Init(true, new KeyParameter(key)); output = wrapper.Wrap(textToWrap, 0, textToWrap.Length); @@ -224,7 +224,7 @@ namespace Org.BouncyCastle.Crypto.Tests output = new byte[expectedWrappedText.Length]; - wrapper = new Dstu7624WrapEngine(128, 256); + wrapper = new Dstu7624WrapEngine(128); wrapper.Init(true, new KeyParameter(key)); output = wrapper.Wrap(textToWrap, 0, textToWrap.Length); @@ -253,7 +253,7 @@ namespace Org.BouncyCastle.Crypto.Tests output = new byte[expectedWrappedText.Length]; - wrapper = new Dstu7624WrapEngine(128, 256); + wrapper = new Dstu7624WrapEngine(128); wrapper.Init(true, new KeyParameter(key)); output = wrapper.Wrap(textToWrap, 0, textToWrap.Length); @@ -282,7 +282,7 @@ namespace Org.BouncyCastle.Crypto.Tests output = new byte[expectedWrappedText.Length]; - wrapper = new Dstu7624WrapEngine(256, 256); + wrapper = new Dstu7624WrapEngine(256); wrapper.Init(true, new KeyParameter(key)); output = wrapper.Wrap(textToWrap, 0, textToWrap.Length); @@ -312,7 +312,7 @@ namespace Org.BouncyCastle.Crypto.Tests output = new byte[expectedWrappedText.Length]; - wrapper = new Dstu7624WrapEngine(256, 256); + wrapper = new Dstu7624WrapEngine(256); wrapper.Init(true, new KeyParameter(key)); output = wrapper.Wrap(textToWrap, 0, textToWrap.Length); @@ -342,7 +342,7 @@ namespace Org.BouncyCastle.Crypto.Tests output = new byte[expectedWrappedText.Length]; - wrapper = new Dstu7624WrapEngine(256, 512); + wrapper = new Dstu7624WrapEngine(256); wrapper.Init(true, new KeyParameter(key)); output = wrapper.Wrap(textToWrap, 0, textToWrap.Length); @@ -371,7 +371,7 @@ namespace Org.BouncyCastle.Crypto.Tests output = new byte[expectedWrappedText.Length]; - wrapper = new Dstu7624WrapEngine(256, 512); + wrapper = new Dstu7624WrapEngine(256); wrapper.Init(true, new KeyParameter(key)); output = wrapper.Wrap(textToWrap, 0, textToWrap.Length); @@ -400,7 +400,7 @@ namespace Org.BouncyCastle.Crypto.Tests output = new byte[expectedWrappedText.Length]; - wrapper = new Dstu7624WrapEngine(512, 512); + wrapper = new Dstu7624WrapEngine(512); wrapper.Init(true, new KeyParameter(key)); output = wrapper.Wrap(textToWrap, 0, textToWrap.Length); @@ -430,7 +430,7 @@ namespace Org.BouncyCastle.Crypto.Tests output = new byte[expectedWrappedText.Length]; - wrapper = new Dstu7624WrapEngine(512, 512); + wrapper = new Dstu7624WrapEngine(512); wrapper.Init(true, new KeyParameter(key)); output = wrapper.Wrap(textToWrap, 0, textToWrap.Length); -- cgit 1.4.1