diff --git a/crypto/src/crypto/digests/GOST3411Digest.cs b/crypto/src/crypto/digests/GOST3411Digest.cs
index 9f0bec9e6..218adf68c 100644
--- a/crypto/src/crypto/digests/GOST3411Digest.cs
+++ b/crypto/src/crypto/digests/GOST3411Digest.cs
@@ -11,7 +11,7 @@ namespace Org.BouncyCastle.Crypto.Digests
* implementation of GOST R 34.11-94
*/
public class Gost3411Digest
- : IDigest
+ : IDigest, IMemoable
{
private const int DIGEST_LENGTH = 32;
@@ -24,7 +24,7 @@ namespace Org.BouncyCastle.Crypto.Digests
private ulong byteCount;
private readonly IBlockCipher cipher = new Gost28147Engine();
- private readonly byte[] sBox;
+ private byte[] sBox;
private static byte[][] MakeC()
{
@@ -65,22 +65,7 @@ namespace Org.BouncyCastle.Crypto.Digests
*/
public Gost3411Digest(Gost3411Digest t)
{
- this.sBox = t.sBox;
- cipher.Init(true, new ParametersWithSBox(null, sBox));
-
- Reset();
-
- Array.Copy(t.H, 0, this.H, 0, t.H.Length);
- Array.Copy(t.L, 0, this.L, 0, t.L.Length);
- Array.Copy(t.M, 0, this.M, 0, t.M.Length);
- Array.Copy(t.Sum, 0, this.Sum, 0, t.Sum.Length);
- Array.Copy(t.C[1], 0, this.C[1], 0, t.C[1].Length);
- Array.Copy(t.C[2], 0, this.C[2], 0, t.C[2].Length);
- Array.Copy(t.C[3], 0, this.C[3], 0, t.C[3].Length);
- Array.Copy(t.xBuf, 0, this.xBuf, 0, t.xBuf.Length);
-
- this.xBufOff = t.xBufOff;
- this.byteCount = t.byteCount;
+ Reset(t);
}
public string AlgorithmName
@@ -339,5 +324,33 @@ namespace Org.BouncyCastle.Crypto.Digests
{
return 32;
}
+
+ public IMemoable Copy()
+ {
+ return new Gost3411Digest(this);
+ }
+
+ public void Reset(IMemoable other)
+ {
+ Gost3411Digest t = (Gost3411Digest)other;
+
+ this.sBox = t.sBox;
+ cipher.Init(true, new ParametersWithSBox(null, sBox));
+
+ Reset();
+
+ Array.Copy(t.H, 0, this.H, 0, t.H.Length);
+ Array.Copy(t.L, 0, this.L, 0, t.L.Length);
+ Array.Copy(t.M, 0, this.M, 0, t.M.Length);
+ Array.Copy(t.Sum, 0, this.Sum, 0, t.Sum.Length);
+ Array.Copy(t.C[1], 0, this.C[1], 0, t.C[1].Length);
+ Array.Copy(t.C[2], 0, this.C[2], 0, t.C[2].Length);
+ Array.Copy(t.C[3], 0, this.C[3], 0, t.C[3].Length);
+ Array.Copy(t.xBuf, 0, this.xBuf, 0, t.xBuf.Length);
+
+ this.xBufOff = t.xBufOff;
+ this.byteCount = t.byteCount;
+ }
}
+
}
diff --git a/crypto/src/crypto/digests/GeneralDigest.cs b/crypto/src/crypto/digests/GeneralDigest.cs
index 77c17ed58..54a09ae05 100644
--- a/crypto/src/crypto/digests/GeneralDigest.cs
+++ b/crypto/src/crypto/digests/GeneralDigest.cs
@@ -1,5 +1,7 @@
using System;
+using Org.BouncyCastle.Utilities;
+
namespace Org.BouncyCastle.Crypto.Digests
{
/**
@@ -7,7 +9,7 @@ namespace Org.BouncyCastle.Crypto.Digests
* "Handbook of Applied Cryptography", pages 344 - 347.
*/
public abstract class GeneralDigest
- : IDigest
+ : IDigest, IMemoable
{
private const int BYTE_LENGTH = 64;
@@ -22,8 +24,13 @@ namespace Org.BouncyCastle.Crypto.Digests
}
internal GeneralDigest(GeneralDigest t)
- {
- xBuf = new byte[t.xBuf.Length];
+ {
+ xBuf = new byte[t.xBuf.Length];
+ CopyIn(t);
+ }
+
+ protected void CopyIn(GeneralDigest t)
+ {
Array.Copy(t.xBuf, 0, xBuf, 0, t.xBuf.Length);
xBufOff = t.xBufOff;
@@ -114,5 +121,7 @@ namespace Org.BouncyCastle.Crypto.Digests
public abstract string AlgorithmName { get; }
public abstract int GetDigestSize();
public abstract int DoFinal(byte[] output, int outOff);
+ public abstract IMemoable Copy();
+ public abstract void Reset(IMemoable t);
}
}
diff --git a/crypto/src/crypto/digests/LongDigest.cs b/crypto/src/crypto/digests/LongDigest.cs
index 702753b2b..9ee9bcd57 100644
--- a/crypto/src/crypto/digests/LongDigest.cs
+++ b/crypto/src/crypto/digests/LongDigest.cs
@@ -2,6 +2,7 @@ using System;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Digests
{
@@ -9,7 +10,7 @@ namespace Org.BouncyCastle.Crypto.Digests
* Base class for SHA-384 and SHA-512.
*/
public abstract class LongDigest
- : IDigest
+ : IDigest, IMemoable
{
private int MyByteLength = 128;
@@ -41,8 +42,14 @@ namespace Org.BouncyCastle.Crypto.Digests
*/
internal LongDigest(
LongDigest t)
- {
- xBuf = new byte[t.xBuf.Length];
+ {
+ xBuf = new byte[t.xBuf.Length];
+
+ CopyIn(t);
+ }
+
+ protected void CopyIn(LongDigest t)
+ {
Array.Copy(t.xBuf, 0, xBuf, 0, t.xBuf.Length);
xBufOff = t.xBufOff;
@@ -342,5 +349,7 @@ namespace Org.BouncyCastle.Crypto.Digests
public abstract string AlgorithmName { get; }
public abstract int GetDigestSize();
public abstract int DoFinal(byte[] output, int outOff);
+ public abstract IMemoable Copy();
+ public abstract void Reset(IMemoable t);
}
}
diff --git a/crypto/src/crypto/digests/MD2Digest.cs b/crypto/src/crypto/digests/MD2Digest.cs
index 78c696f33..6d90f3f9d 100644
--- a/crypto/src/crypto/digests/MD2Digest.cs
+++ b/crypto/src/crypto/digests/MD2Digest.cs
@@ -1,5 +1,7 @@
using System;
+
using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Digests
{
@@ -9,7 +11,7 @@ namespace Org.BouncyCastle.Crypto.Digests
* as outlined in RFC1319 by B.Kaliski from RSA Laboratories April 1992
*/
public class MD2Digest
- : IDigest
+ : IDigest, IMemoable
{
private const int DigestLength = 16;
private const int BYTE_LENGTH = 16;
@@ -32,8 +34,14 @@ namespace Org.BouncyCastle.Crypto.Digests
{
Reset();
}
+
public MD2Digest(MD2Digest t)
- {
+ {
+ CopyIn(t);
+ }
+
+ private void CopyIn(MD2Digest t)
+ {
Array.Copy(t.X, 0, X, 0, t.X.Length);
xOff = t.xOff;
Array.Copy(t.M, 0, M, 0, t.M.Length);
@@ -41,6 +49,7 @@ namespace Org.BouncyCastle.Crypto.Digests
Array.Copy(t.C, 0, C, 0, t.C.Length);
COff = t.COff;
}
+
/**
* return the algorithm name
*
@@ -242,6 +251,19 @@ namespace Org.BouncyCastle.Crypto.Digests
(byte)237,(byte)31,(byte)26,(byte)219,(byte)153,(byte)141,(byte)51,
(byte)159,(byte)17,(byte)131,(byte)20
};
+
+ public IMemoable Copy()
+ {
+ return new MD2Digest(this);
+ }
+
+ public void Reset(IMemoable other)
+ {
+ MD2Digest d = (MD2Digest)other;
+
+ CopyIn(d);
+ }
+
}
}
diff --git a/crypto/src/crypto/digests/MD4Digest.cs b/crypto/src/crypto/digests/MD4Digest.cs
index bc4eae0fd..8743f7dad 100644
--- a/crypto/src/crypto/digests/MD4Digest.cs
+++ b/crypto/src/crypto/digests/MD4Digest.cs
@@ -1,5 +1,7 @@
using System;
+using Org.BouncyCastle.Utilities;
+
namespace Org.BouncyCastle.Crypto.Digests
{
/**
@@ -32,7 +34,13 @@ namespace Org.BouncyCastle.Crypto.Digests
* message digest.
*/
public MD4Digest(MD4Digest t) : base(t)
- {
+ {
+ CopyIn(t);
+ }
+
+ private void CopyIn(MD4Digest t)
+ {
+ base.CopyIn(t);
H1 = t.H1;
H2 = t.H2;
H3 = t.H3;
@@ -266,6 +274,19 @@ namespace Org.BouncyCastle.Crypto.Digests
X[i] = 0;
}
}
+
+ public override IMemoable Copy()
+ {
+ return new MD4Digest(this);
+ }
+
+ public override void Reset(IMemoable other)
+ {
+ MD4Digest d = (MD4Digest)other;
+
+ CopyIn(d);
+ }
+
}
}
diff --git a/crypto/src/crypto/digests/MD5Digest.cs b/crypto/src/crypto/digests/MD5Digest.cs
index 2116d64f0..c60ac92a3 100644
--- a/crypto/src/crypto/digests/MD5Digest.cs
+++ b/crypto/src/crypto/digests/MD5Digest.cs
@@ -1,6 +1,7 @@
using System;
using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Digests
{
@@ -28,7 +29,13 @@ namespace Org.BouncyCastle.Crypto.Digests
*/
public MD5Digest(MD5Digest t)
: base(t)
- {
+ {
+ CopyIn(t);
+ }
+
+ private void CopyIn(MD5Digest t)
+ {
+ base.CopyIn(t);
H1 = t.H1;
H2 = t.H2;
H3 = t.H3;
@@ -287,7 +294,20 @@ namespace Org.BouncyCastle.Crypto.Digests
xOff = 0;
}
- }
+
+ public override IMemoable Copy()
+ {
+ return new MD5Digest(this);
+ }
+
+ public override void Reset(IMemoable other)
+ {
+ MD5Digest d = (MD5Digest)other;
+
+ CopyIn(d);
+ }
+
+ }
}
diff --git a/crypto/src/crypto/digests/RipeMD128Digest.cs b/crypto/src/crypto/digests/RipeMD128Digest.cs
index 8977583a4..e8a0331ca 100644
--- a/crypto/src/crypto/digests/RipeMD128Digest.cs
+++ b/crypto/src/crypto/digests/RipeMD128Digest.cs
@@ -1,5 +1,7 @@
using System;
+using Org.BouncyCastle.Utilities;
+
namespace Org.BouncyCastle.Crypto.Digests
{
/**
@@ -28,8 +30,15 @@ namespace Org.BouncyCastle.Crypto.Digests
* message digest.
*/
public RipeMD128Digest(RipeMD128Digest t) : base(t)
- {
- H0 = t.H0;
+ {
+ CopyIn(t);
+ }
+
+ private void CopyIn(RipeMD128Digest t)
+ {
+ base.CopyIn(t);
+
+ H0 = t.H0;
H1 = t.H1;
H2 = t.H2;
H3 = t.H3;
@@ -457,6 +466,19 @@ namespace Org.BouncyCastle.Crypto.Digests
X[i] = 0;
}
}
+
+ public override IMemoable Copy()
+ {
+ return new RipeMD128Digest(this);
+ }
+
+ public override void Reset(IMemoable other)
+ {
+ RipeMD128Digest d = (RipeMD128Digest)other;
+
+ CopyIn(d);
+ }
+
}
}
diff --git a/crypto/src/crypto/digests/RipeMD160Digest.cs b/crypto/src/crypto/digests/RipeMD160Digest.cs
index 8ce52ae58..af4aa44bb 100644
--- a/crypto/src/crypto/digests/RipeMD160Digest.cs
+++ b/crypto/src/crypto/digests/RipeMD160Digest.cs
@@ -1,5 +1,7 @@
using System;
+using Org.BouncyCastle.Utilities;
+
namespace Org.BouncyCastle.Crypto.Digests
{
/**
@@ -30,6 +32,13 @@ namespace Org.BouncyCastle.Crypto.Digests
*/
public RipeMD160Digest(RipeMD160Digest t) : base(t)
{
+ CopyIn(t);
+ }
+
+ private void CopyIn(RipeMD160Digest t)
+ {
+ base.CopyIn(t);
+
H0 = t.H0;
H1 = t.H1;
H2 = t.H2;
@@ -418,6 +427,19 @@ namespace Org.BouncyCastle.Crypto.Digests
X[i] = 0;
}
}
+
+ public override IMemoable Copy()
+ {
+ return new RipeMD160Digest(this);
+ }
+
+ public override void Reset(IMemoable other)
+ {
+ RipeMD160Digest d = (RipeMD160Digest)other;
+
+ CopyIn(d);
+ }
+
}
}
diff --git a/crypto/src/crypto/digests/RipeMD256Digest.cs b/crypto/src/crypto/digests/RipeMD256Digest.cs
index 950e94f80..306275767 100644
--- a/crypto/src/crypto/digests/RipeMD256Digest.cs
+++ b/crypto/src/crypto/digests/RipeMD256Digest.cs
@@ -1,5 +1,7 @@
using System;
+using Org.BouncyCastle.Utilities;
+
namespace Org.BouncyCastle.Crypto.Digests
{
/// <remarks>
@@ -37,6 +39,12 @@ namespace Org.BouncyCastle.Crypto.Digests
/// </summary>
public RipeMD256Digest(RipeMD256Digest t):base(t)
{
+ CopyIn(t);
+ }
+
+ private void CopyIn(RipeMD256Digest t)
+ {
+ base.CopyIn(t);
H0 = t.H0;
H1 = t.H1;
@@ -405,5 +413,18 @@ namespace Org.BouncyCastle.Crypto.Digests
X[i] = 0;
}
}
+
+ public override IMemoable Copy()
+ {
+ return new RipeMD256Digest(this);
+ }
+
+ public override void Reset(IMemoable other)
+ {
+ RipeMD256Digest d = (RipeMD256Digest)other;
+
+ CopyIn(d);
+ }
+
}
}
diff --git a/crypto/src/crypto/digests/RipeMD320Digest.cs b/crypto/src/crypto/digests/RipeMD320Digest.cs
index 25c74baef..767d74dba 100644
--- a/crypto/src/crypto/digests/RipeMD320Digest.cs
+++ b/crypto/src/crypto/digests/RipeMD320Digest.cs
@@ -1,5 +1,7 @@
using System;
+using Org.BouncyCastle.Utilities;
+
namespace Org.BouncyCastle.Crypto.Digests
{
/// <remarks>
@@ -38,6 +40,12 @@ namespace Org.BouncyCastle.Crypto.Digests
public RipeMD320Digest(RipeMD320Digest t)
: base(t)
{
+ CopyIn(t);
+ }
+
+ private void CopyIn(RipeMD320Digest t)
+ {
+ base.CopyIn(t);
H0 = t.H0;
H1 = t.H1;
@@ -434,5 +442,18 @@ namespace Org.BouncyCastle.Crypto.Digests
X[i] = 0;
}
}
+
+ public override IMemoable Copy()
+ {
+ return new RipeMD320Digest(this);
+ }
+
+ public override void Reset(IMemoable other)
+ {
+ RipeMD320Digest d = (RipeMD320Digest)other;
+
+ CopyIn(d);
+ }
+
}
}
diff --git a/crypto/src/crypto/digests/SHA3Digest.cs b/crypto/src/crypto/digests/SHA3Digest.cs
index a115495f4..2c6837b3c 100644
--- a/crypto/src/crypto/digests/SHA3Digest.cs
+++ b/crypto/src/crypto/digests/SHA3Digest.cs
@@ -11,7 +11,7 @@ namespace Org.BouncyCastle.Crypto.Digests
/// Following the naming conventions used in the C source code to enable easy review of the implementation.
/// </remarks>
public class Sha3Digest
- : IDigest
+ : IDigest, IMemoable
{
private static readonly ulong[] KeccakRoundConstants = KeccakInitializeRoundConstants();
@@ -103,6 +103,11 @@ namespace Org.BouncyCastle.Crypto.Digests
public Sha3Digest(Sha3Digest source)
{
+ CopyIn(source);
+ }
+
+ private void CopyIn(Sha3Digest source)
+ {
Array.Copy(source.state, 0, this.state, 0, source.state.Length);
Array.Copy(source.dataQueue, 0, this.dataQueue, 0, source.dataQueue.Length);
this.rate = source.rate;
@@ -537,5 +542,19 @@ namespace Org.BouncyCastle.Crypto.Digests
{
Array.Copy(byteState, 0, data, 0, laneCount * 8);
}
+
+ public IMemoable Copy()
+ {
+ return new Sha3Digest(this);
+ }
+
+ public void Reset(IMemoable other)
+ {
+ Sha3Digest d = (Sha3Digest)other;
+
+ CopyIn(d);
+ }
+
+
}
}
diff --git a/crypto/src/crypto/digests/Sha1Digest.cs b/crypto/src/crypto/digests/Sha1Digest.cs
index e72b84f94..60ec651d5 100644
--- a/crypto/src/crypto/digests/Sha1Digest.cs
+++ b/crypto/src/crypto/digests/Sha1Digest.cs
@@ -1,6 +1,7 @@
using System;
using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Digests
{
@@ -33,6 +34,13 @@ namespace Org.BouncyCastle.Crypto.Digests
public Sha1Digest(Sha1Digest t)
: base(t)
{
+ CopyIn(t);
+ }
+
+ private void CopyIn(Sha1Digest t)
+ {
+ base.CopyIn(t);
+
H1 = t.H1;
H2 = t.H2;
H3 = t.H3;
@@ -259,5 +267,18 @@ namespace Org.BouncyCastle.Crypto.Digests
xOff = 0;
Array.Clear(X, 0, 16);
}
+
+ public override IMemoable Copy()
+ {
+ return new Sha1Digest(this);
+ }
+
+ public override void Reset(IMemoable other)
+ {
+ Sha1Digest d = (Sha1Digest)other;
+
+ CopyIn(d);
+ }
+
}
}
diff --git a/crypto/src/crypto/digests/Sha224Digest.cs b/crypto/src/crypto/digests/Sha224Digest.cs
index 66ecd4ecd..b4e853745 100644
--- a/crypto/src/crypto/digests/Sha224Digest.cs
+++ b/crypto/src/crypto/digests/Sha224Digest.cs
@@ -1,6 +1,7 @@
using System;
using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Digests
{
@@ -41,6 +42,13 @@ namespace Org.BouncyCastle.Crypto.Digests
Sha224Digest t)
: base(t)
{
+ CopyIn(t);
+ }
+
+ private void CopyIn(Sha224Digest t)
+ {
+ base.CopyIn(t);
+
H1 = t.H1;
H2 = t.H2;
H3 = t.H3;
@@ -264,5 +272,18 @@ namespace Org.BouncyCastle.Crypto.Digests
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
+
+ public override IMemoable Copy()
+ {
+ return new Sha224Digest(this);
+ }
+
+ public override void Reset(IMemoable other)
+ {
+ Sha224Digest d = (Sha224Digest)other;
+
+ CopyIn(d);
+ }
+
}
}
diff --git a/crypto/src/crypto/digests/Sha256Digest.cs b/crypto/src/crypto/digests/Sha256Digest.cs
index 1c00ab71f..98e10a34d 100644
--- a/crypto/src/crypto/digests/Sha256Digest.cs
+++ b/crypto/src/crypto/digests/Sha256Digest.cs
@@ -1,6 +1,7 @@
using System;
using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Digests
{
@@ -36,6 +37,13 @@ namespace Org.BouncyCastle.Crypto.Digests
*/
public Sha256Digest(Sha256Digest t) : base(t)
{
+ CopyIn(t);
+ }
+
+ private void CopyIn(Sha256Digest t)
+ {
+ base.CopyIn(t);
+
H1 = t.H1;
H2 = t.H2;
H3 = t.H3;
@@ -305,5 +313,18 @@ namespace Org.BouncyCastle.Crypto.Digests
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
+
+ public override IMemoable Copy()
+ {
+ return new Sha256Digest(this);
+ }
+
+ public override void Reset(IMemoable other)
+ {
+ Sha256Digest d = (Sha256Digest)other;
+
+ CopyIn(d);
+ }
+
}
}
diff --git a/crypto/src/crypto/digests/Sha384Digest.cs b/crypto/src/crypto/digests/Sha384Digest.cs
index f1372d0a9..e6c9a9aa9 100644
--- a/crypto/src/crypto/digests/Sha384Digest.cs
+++ b/crypto/src/crypto/digests/Sha384Digest.cs
@@ -1,6 +1,7 @@
using System;
using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Digests
{
@@ -83,5 +84,18 @@ namespace Org.BouncyCastle.Crypto.Digests
H7 = 0xdb0c2e0d64f98fa7;
H8 = 0x47b5481dbefa4fa4;
}
+
+ public override IMemoable Copy()
+ {
+ return new Sha384Digest(this);
+ }
+
+ public override void Reset(IMemoable other)
+ {
+ Sha384Digest d = (Sha384Digest)other;
+
+ CopyIn(d);
+ }
+
}
}
diff --git a/crypto/src/crypto/digests/Sha512Digest.cs b/crypto/src/crypto/digests/Sha512Digest.cs
index b38ff8ee7..2a0964fd3 100644
--- a/crypto/src/crypto/digests/Sha512Digest.cs
+++ b/crypto/src/crypto/digests/Sha512Digest.cs
@@ -1,6 +1,7 @@
using System;
using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Digests
{
@@ -86,5 +87,18 @@ namespace Org.BouncyCastle.Crypto.Digests
H7 = 0x1f83d9abfb41bd6b;
H8 = 0x5be0cd19137e2179;
}
+
+ public override IMemoable Copy()
+ {
+ return new Sha512Digest(this);
+ }
+
+ public override void Reset(IMemoable other)
+ {
+ Sha512Digest d = (Sha512Digest)other;
+
+ CopyIn(d);
+ }
+
}
}
diff --git a/crypto/src/crypto/digests/Sha512tDigest.cs b/crypto/src/crypto/digests/Sha512tDigest.cs
index 7580d6267..2caefa763 100644
--- a/crypto/src/crypto/digests/Sha512tDigest.cs
+++ b/crypto/src/crypto/digests/Sha512tDigest.cs
@@ -1,6 +1,7 @@
using System;
using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Digests
{
@@ -44,14 +45,7 @@ namespace Org.BouncyCastle.Crypto.Digests
{
this.digestLength = t.digestLength;
- this.H1t = t.H1t;
- this.H2t = t.H2t;
- this.H3t = t.H3t;
- this.H4t = t.H4t;
- this.H5t = t.H5t;
- this.H6t = t.H6t;
- this.H7t = t.H7t;
- this.H8t = t.H8t;
+ Reset(t);
}
public override string AlgorithmName
@@ -175,5 +169,32 @@ namespace Org.BouncyCastle.Crypto.Digests
bs[off + num] = (byte)(n >> shift);
}
}
- }
+
+ public override IMemoable Copy()
+ {
+ return new Sha512tDigest(this);
+ }
+
+ public override void Reset(IMemoable other)
+ {
+ Sha512tDigest t = (Sha512tDigest)other;
+
+ if (this.digestLength != t.digestLength)
+ {
+ throw new MemoableResetException("digestLength inappropriate in other");
+ }
+
+ base.CopyIn(t);
+
+ this.H1t = t.H1t;
+ this.H2t = t.H2t;
+ this.H3t = t.H3t;
+ this.H4t = t.H4t;
+ this.H5t = t.H5t;
+ this.H6t = t.H6t;
+ this.H7t = t.H7t;
+ this.H8t = t.H8t;
+ }
+
+ }
}
diff --git a/crypto/src/crypto/digests/SkeinDigest.cs b/crypto/src/crypto/digests/SkeinDigest.cs
new file mode 100644
index 000000000..f826ce503
--- /dev/null
+++ b/crypto/src/crypto/digests/SkeinDigest.cs
@@ -0,0 +1,117 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Digests
+{
+
+ /// <summary>
+ /// Implementation of the Skein parameterised hash function in 256, 512 and 1024 bit block sizes,
+ /// based on the <see cref="Org.BouncyCastle.Crypto.Engines.ThreefishEngine">Threefish</see> tweakable block cipher.
+ /// </summary>
+ /// <remarks>
+ /// This is the 1.3 version of Skein defined in the Skein hash function submission to the NIST SHA-3
+ /// competition in October 2010.
+ /// <p/>
+ /// Skein was designed by Niels Ferguson - Stefan Lucks - Bruce Schneier - Doug Whiting - Mihir
+ /// Bellare - Tadayoshi Kohno - Jon Callas - Jesse Walker.
+ /// </remarks>
+ /// <seealso cref="Org.BouncyCastle.Crypto.Digests.SkeinEngine"/>
+ /// <seealso cref="Org.BouncyCastle.Crypto.Parameters.SkeinParameters"/>
+ public class SkeinDigest
+ : IDigest, IMemoable
+ {
+ /// <summary>
+ /// 256 bit block size - Skein-256
+ /// </summary>
+ public const int SKEIN_256 = SkeinEngine.SKEIN_256;
+ /// <summary>
+ /// 512 bit block size - Skein-512
+ /// </summary>
+ public const int SKEIN_512 = SkeinEngine.SKEIN_512;
+ /// <summary>
+ /// 1024 bit block size - Skein-1024
+ /// </summary>
+ public const int SKEIN_1024 = SkeinEngine.SKEIN_1024;
+
+ private readonly SkeinEngine engine;
+
+ /// <summary>
+ /// Constructs a Skein digest with an internal state size and output size.
+ /// </summary>
+ /// <param name="stateSizeBits">the internal state size in bits - one of <see cref="SKEIN_256"/> <see cref="SKEIN_512"/> or
+ /// <see cref="SKEIN_1024"/>.</param>
+ /// <param name="digestSizeBits">the output/digest size to produce in bits, which must be an integral number of
+ /// bytes.</param>
+ public SkeinDigest(int stateSizeBits, int digestSizeBits)
+ {
+ this.engine = new SkeinEngine(stateSizeBits, digestSizeBits);
+ Init(null);
+ }
+
+ public SkeinDigest(SkeinDigest digest)
+ {
+ this.engine = new SkeinEngine(digest.engine);
+ }
+
+ public void Reset(IMemoable other)
+ {
+ SkeinDigest d = (SkeinDigest)other;
+ engine.Reset(d.engine);
+ }
+
+ public IMemoable Copy()
+ {
+ return new SkeinDigest(this);
+ }
+
+ public String AlgorithmName
+ {
+ get { return "Skein-" + (engine.BlockSize * 8) + "-" + (engine.OutputSize * 8); }
+ }
+
+ public int GetDigestSize()
+ {
+ return engine.OutputSize;
+ }
+
+ public int GetByteLength()
+ {
+ return engine.BlockSize;
+ }
+
+ /// <summary>
+ /// Optionally initialises the Skein digest with the provided parameters.
+ /// </summary>
+ /// See <see cref="Org.BouncyCastle.Crypto.Parameters.SkeinParameters"></see> for details on the parameterisation of the Skein hash function.
+ /// <param name="parameters">the parameters to apply to this engine, or <code>null</code> to use no parameters.</param>
+ public void Init(SkeinParameters parameters)
+ {
+ engine.Init(parameters);
+ }
+
+ public void Reset()
+ {
+ engine.Reset();
+ }
+
+ public void Update(byte inByte)
+ {
+ engine.Update(inByte);
+ }
+
+ public void BlockUpdate(byte[] inBytes, int inOff, int len)
+ {
+ engine.Update(inBytes, inOff, len);
+ }
+
+ public int DoFinal(byte[] outBytes, int outOff)
+ {
+ return engine.DoFinal(outBytes, outOff);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/crypto/src/crypto/digests/SkeinEngine.cs b/crypto/src/crypto/digests/SkeinEngine.cs
new file mode 100644
index 000000000..49ec51304
--- /dev/null
+++ b/crypto/src/crypto/digests/SkeinEngine.cs
@@ -0,0 +1,803 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Digests
+{
+
+ /// <summary>
+ /// Implementation of the Skein family of parameterised hash functions in 256, 512 and 1024 bit block
+ /// sizes, based on the <see cref="Org.BouncyCastle.Crypto.Engines.ThreefishEngine">Threefish</see> tweakable block cipher.
+ /// </summary>
+ /// <remarks>
+ /// This is the 1.3 version of Skein defined in the Skein hash function submission to the NIST SHA-3
+ /// competition in October 2010.
+ /// <p/>
+ /// Skein was designed by Niels Ferguson - Stefan Lucks - Bruce Schneier - Doug Whiting - Mihir
+ /// Bellare - Tadayoshi Kohno - Jon Callas - Jesse Walker.
+ /// <p/>
+ /// This implementation is the basis for <see cref="Org.BouncyCastle.Crypto.Digests.SkeinDigest"/> and <see cref="Org.BouncyCastle.Crypto.Macs.SkeinMac"/>, implementing the
+ /// parameter based configuration system that allows Skein to be adapted to multiple applications. <br>
+ /// Initialising the engine with <see cref="Org.BouncyCastle.Crypto.Parameters.SkeinParameters"/> allows standard and arbitrary parameters to
+ /// be applied during the Skein hash function.
+ /// <p/>
+ /// Implemented:
+ /// <ul>
+ /// <li>256, 512 and 1024 bit internal states.</li>
+ /// <li>Full 96 bit input length.</li>
+ /// <li>Parameters defined in the Skein specification, and arbitrary other pre and post message
+ /// parameters.</li>
+ /// <li>Arbitrary output size in 1 byte intervals.</li>
+ /// </ul>
+ /// <p/>
+ /// Not implemented:
+ /// <ul>
+ /// <li>Sub-byte length input (bit padding).</li>
+ /// <li>Tree hashing.</li>
+ /// </ul>
+ /// </remarks>
+ /// <seealso cref="Org.BouncyCastle.Crypto.Parameters.SkeinParameters"/>
+ public class SkeinEngine
+ : IMemoable
+ {
+ /// <summary>
+ /// 256 bit block size - Skein-256
+ /// </summary>
+ public const int SKEIN_256 = ThreefishEngine.BLOCKSIZE_256;
+ /// <summary>
+ /// 512 bit block size - Skein-512
+ /// </summary>
+ public const int SKEIN_512 = ThreefishEngine.BLOCKSIZE_512;
+ /// <summary>
+ /// 1024 bit block size - Skein-1024
+ /// </summary>
+ public const int SKEIN_1024 = ThreefishEngine.BLOCKSIZE_1024;
+
+ // Minimal at present, but more complex when tree hashing is implemented
+ private class Configuration
+ {
+ private byte[] bytes = new byte[32];
+
+ public Configuration(long outputSizeBits)
+ {
+ // 0..3 = ASCII SHA3
+ bytes[0] = (byte)'S';
+ bytes[1] = (byte)'H';
+ bytes[2] = (byte)'A';
+ bytes[3] = (byte)'3';
+
+ // 4..5 = version number in LSB order
+ bytes[4] = 1;
+ bytes[5] = 0;
+
+ // 8..15 = output length
+ ThreefishEngine.WordToBytes((ulong)outputSizeBits, bytes, 8);
+ }
+
+ public byte[] Bytes
+ {
+ get { return bytes; }
+ }
+
+ }
+
+ public class Parameter
+ {
+ private int type;
+ private byte[] value;
+
+ public Parameter(int type, byte[] value)
+ {
+ this.type = type;
+ this.value = value;
+ }
+
+ public int Type
+ {
+ get { return type; }
+ }
+
+ public byte[] Value
+ {
+ get { return value; }
+ }
+
+ }
+
+ /**
+ * The parameter type for the Skein key.
+ */
+ private const int PARAM_TYPE_KEY = 0;
+
+ /**
+ * The parameter type for the Skein configuration block.
+ */
+ private const int PARAM_TYPE_CONFIG = 4;
+
+ /**
+ * The parameter type for the message.
+ */
+ private const int PARAM_TYPE_MESSAGE = 48;
+
+ /**
+ * The parameter type for the output transformation.
+ */
+ private const int PARAM_TYPE_OUTPUT = 63;
+
+ /**
+ * Precalculated UBI(CFG) states for common state/output combinations without key or other
+ * pre-message params.
+ */
+ private static readonly IDictionary INITIAL_STATES = Platform.CreateHashtable();
+
+ static SkeinEngine()
+ {
+ // From Appendix C of the Skein 1.3 NIST submission
+ InitialState(SKEIN_256, 128, new ulong[]{
+ 0xe1111906964d7260UL,
+ 0x883daaa77c8d811cUL,
+ 0x10080df491960f7aUL,
+ 0xccf7dde5b45bc1c2UL});
+
+ InitialState(SKEIN_256, 160, new ulong[]{
+ 0x1420231472825e98UL,
+ 0x2ac4e9a25a77e590UL,
+ 0xd47a58568838d63eUL,
+ 0x2dd2e4968586ab7dUL});
+
+ InitialState(SKEIN_256, 224, new ulong[]{
+ 0xc6098a8c9ae5ea0bUL,
+ 0x876d568608c5191cUL,
+ 0x99cb88d7d7f53884UL,
+ 0x384bddb1aeddb5deUL});
+
+ InitialState(SKEIN_256, 256, new ulong[]{
+ 0xfc9da860d048b449UL,
+ 0x2fca66479fa7d833UL,
+ 0xb33bc3896656840fUL,
+ 0x6a54e920fde8da69UL});
+
+ InitialState(SKEIN_512, 128, new ulong[]{
+ 0xa8bc7bf36fbf9f52UL,
+ 0x1e9872cebd1af0aaUL,
+ 0x309b1790b32190d3UL,
+ 0xbcfbb8543f94805cUL,
+ 0x0da61bcd6e31b11bUL,
+ 0x1a18ebead46a32e3UL,
+ 0xa2cc5b18ce84aa82UL,
+ 0x6982ab289d46982dUL});
+
+ InitialState(SKEIN_512, 160, new ulong[]{
+ 0x28b81a2ae013bd91UL,
+ 0xc2f11668b5bdf78fUL,
+ 0x1760d8f3f6a56f12UL,
+ 0x4fb747588239904fUL,
+ 0x21ede07f7eaf5056UL,
+ 0xd908922e63ed70b8UL,
+ 0xb8ec76ffeccb52faUL,
+ 0x01a47bb8a3f27a6eUL});
+
+ InitialState(SKEIN_512, 224, new ulong[]{
+ 0xccd0616248677224UL,
+ 0xcba65cf3a92339efUL,
+ 0x8ccd69d652ff4b64UL,
+ 0x398aed7b3ab890b4UL,
+ 0x0f59d1b1457d2bd0UL,
+ 0x6776fe6575d4eb3dUL,
+ 0x99fbc70e997413e9UL,
+ 0x9e2cfccfe1c41ef7UL});
+
+ InitialState(SKEIN_512, 384, new ulong[]{
+ 0xa3f6c6bf3a75ef5fUL,
+ 0xb0fef9ccfd84faa4UL,
+ 0x9d77dd663d770cfeUL,
+ 0xd798cbf3b468fddaUL,
+ 0x1bc4a6668a0e4465UL,
+ 0x7ed7d434e5807407UL,
+ 0x548fc1acd4ec44d6UL,
+ 0x266e17546aa18ff8UL});
+
+ InitialState(SKEIN_512, 512, new ulong[]{
+ 0x4903adff749c51ceUL,
+ 0x0d95de399746df03UL,
+ 0x8fd1934127c79bceUL,
+ 0x9a255629ff352cb1UL,
+ 0x5db62599df6ca7b0UL,
+ 0xeabe394ca9d5c3f4UL,
+ 0x991112c71a75b523UL,
+ 0xae18a40b660fcc33UL});
+ }
+
+ private static void InitialState(int blockSize, int outputSize, ulong[] state)
+ {
+ INITIAL_STATES.Add(VariantIdentifier(blockSize / 8, outputSize / 8), state);
+ }
+
+ private static int VariantIdentifier(int blockSizeBytes, int outputSizeBytes)
+ {
+ return (outputSizeBytes << 16) | blockSizeBytes;
+ }
+
+ private class UbiTweak
+ {
+ /**
+ * Point at which position might overflow long, so switch to add with carry logic
+ */
+ private const ulong LOW_RANGE = UInt64.MaxValue - UInt32.MaxValue;
+
+ /**
+ * Bit 127 = final
+ */
+ private const ulong T1_FINAL = 1UL << 63;
+
+ /**
+ * Bit 126 = first
+ */
+ private const ulong T1_FIRST = 1UL << 62;
+
+ /**
+ * UBI uses a 128 bit tweak
+ */
+ private ulong[] tweak = new ulong[2];
+
+ /**
+ * Whether 64 bit position exceeded
+ */
+ private bool extendedPosition;
+
+ public UbiTweak()
+ {
+ Reset();
+ }
+
+ public void Reset(UbiTweak tweak)
+ {
+ this.tweak = Arrays.Clone(tweak.tweak, this.tweak);
+ this.extendedPosition = tweak.extendedPosition;
+ }
+
+ public void Reset()
+ {
+ tweak[0] = 0;
+ tweak[1] = 0;
+ extendedPosition = false;
+ First = true;
+ }
+
+ public uint Type
+ {
+ get
+ {
+ return (uint)((tweak[1] >> 56) & 0x3FUL);
+ }
+
+ set
+ {
+ // Bits 120..125 = type
+ tweak[1] = (tweak[1] & 0xFFFFFFC000000000UL) | ((value & 0x3FUL) << 56);
+ }
+ }
+
+ public bool First
+ {
+ get
+ {
+ return ((tweak[1] & T1_FIRST) != 0);
+ }
+ set
+ {
+ if (value)
+ {
+ tweak[1] |= T1_FIRST;
+ }
+ else
+ {
+ tweak[1] &= ~T1_FIRST;
+ }
+ }
+ }
+
+ public bool Final
+ {
+ get
+ {
+ return ((tweak[1] & T1_FINAL) != 0);
+ }
+ set
+ {
+ if (value)
+ {
+ tweak[1] |= T1_FINAL;
+ }
+ else
+ {
+ tweak[1] &= ~T1_FINAL;
+ }
+ }
+ }
+
+ /**
+ * Advances the position in the tweak by the specified value.
+ */
+ public void AdvancePosition(int advance)
+ {
+ // Bits 0..95 = position
+ if (extendedPosition)
+ {
+ ulong[] parts = new ulong[3];
+ parts[0] = tweak[0] & 0xFFFFFFFFUL;
+ parts[1] = (tweak[0] >> 32) & 0xFFFFFFFFUL;
+ parts[2] = tweak[1] & 0xFFFFFFFFUL;
+
+ ulong carry = (ulong)advance;
+ for (int i = 0; i < parts.Length; i++)
+ {
+ carry += parts[i];
+ parts[i] = carry;
+ carry >>= 32;
+ }
+ tweak[0] = ((parts[1] & 0xFFFFFFFFUL) << 32) | (parts[0] & 0xFFFFFFFFUL);
+ tweak[1] = (tweak[1] & 0xFFFFFFFF00000000UL) | (parts[2] & 0xFFFFFFFFUL);
+ }
+ else
+ {
+ ulong position = tweak[0];
+ position += (uint)advance;
+ tweak[0] = position;
+ if (position > LOW_RANGE)
+ {
+ extendedPosition = true;
+ }
+ }
+ }
+
+ public ulong[] GetWords()
+ {
+ return tweak;
+ }
+
+ public override string ToString()
+ {
+ return Type + " first: " + First + ", final: " + Final;
+ }
+
+ }
+
+ /**
+ * The Unique Block Iteration chaining mode.
+ */
+ // TODO: This might be better as methods...
+ private class UBI
+ {
+ private readonly UbiTweak tweak = new UbiTweak();
+
+ private readonly SkeinEngine engine;
+
+ /**
+ * Buffer for the current block of message data
+ */
+ private byte[] currentBlock;
+
+ /**
+ * Offset into the current message block
+ */
+ private int currentOffset;
+
+ /**
+ * Buffer for message words for feedback into encrypted block
+ */
+ private ulong[] message;
+
+ public UBI(SkeinEngine engine, int blockSize)
+ {
+ this.engine = engine;
+ currentBlock = new byte[blockSize];
+ message = new ulong[currentBlock.Length / 8];
+ }
+
+ public void Reset(UBI ubi)
+ {
+ currentBlock = Arrays.Clone(ubi.currentBlock, currentBlock);
+ currentOffset = ubi.currentOffset;
+ message = Arrays.Clone(ubi.message, this.message);
+ tweak.Reset(ubi.tweak);
+ }
+
+ public void Reset(int type)
+ {
+ tweak.Reset();
+ tweak.Type = (uint)type;
+ currentOffset = 0;
+ }
+
+ public void Update(byte[] value, int offset, int len, ulong[] output)
+ {
+ /*
+ * Buffer complete blocks for the underlying Threefish cipher, only flushing when there
+ * are subsequent bytes (last block must be processed in doFinal() with final=true set).
+ */
+ int copied = 0;
+ while (len > copied)
+ {
+ if (currentOffset == currentBlock.Length)
+ {
+ ProcessBlock(output);
+ tweak.First = false;
+ currentOffset = 0;
+ }
+
+ int toCopy = System.Math.Min((len - copied), currentBlock.Length - currentOffset);
+ Array.Copy(value, offset + copied, currentBlock, currentOffset, toCopy);
+ copied += toCopy;
+ currentOffset += toCopy;
+ tweak.AdvancePosition(toCopy);
+ }
+ }
+
+ private void ProcessBlock(ulong[] output)
+ {
+ engine.threefish.Init(true, engine.chain, tweak.GetWords());
+ for (int i = 0; i < message.Length; i++)
+ {
+ message[i] = ThreefishEngine.BytesToWord(currentBlock, i * 8);
+ }
+
+ engine.threefish.ProcessBlock(message, output);
+
+ for (int i = 0; i < output.Length; i++)
+ {
+ output[i] ^= message[i];
+ }
+ }
+
+ public void DoFinal(ulong[] output)
+ {
+ // Pad remainder of current block with zeroes
+ for (int i = currentOffset; i < currentBlock.Length; i++)
+ {
+ currentBlock[i] = 0;
+ }
+
+ tweak.Final = true;
+ ProcessBlock(output);
+ }
+
+ }
+
+ /**
+ * Underlying Threefish tweakable block cipher
+ */
+ private readonly ThreefishEngine threefish;
+
+ /**
+ * Size of the digest output, in bytes
+ */
+ private readonly int outputSizeBytes;
+
+ /**
+ * The current chaining/state value
+ */
+ private ulong[] chain;
+
+ /**
+ * The initial state value
+ */
+ private ulong[] initialState;
+
+ /**
+ * The (optional) key parameter
+ */
+ private byte[] key;
+
+ /**
+ * Parameters to apply prior to the message
+ */
+ private Parameter[] preMessageParameters;
+
+ /**
+ * Parameters to apply after the message, but prior to output
+ */
+ private Parameter[] postMessageParameters;
+
+ /**
+ * The current UBI operation
+ */
+ private readonly UBI ubi;
+
+ /**
+ * Buffer for single byte update method
+ */
+ private readonly byte[] singleByte = new byte[1];
+
+ /// <summary>
+ /// Constructs a Skein digest with an internal state size and output size.
+ /// </summary>
+ /// <param name="stateSizeBits">the internal state size in bits - one of <see cref="SKEIN_256"/> <see cref="SKEIN_512"/> or
+ /// <see cref="SKEIN_1024"/>.</param>
+ /// <param name="outputSizeBits">the output/digest size to produce in bits, which must be an integral number of
+ /// bytes.</param>
+ public SkeinEngine(int blockSizeBits, int outputSizeBits)
+ {
+ if (outputSizeBits % 8 != 0)
+ {
+ throw new ArgumentException("Output size must be a multiple of 8 bits. :" + outputSizeBits);
+ }
+ // TODO: Prevent digest sizes > block size?
+ this.outputSizeBytes = outputSizeBits / 8;
+
+ this.threefish = new ThreefishEngine(blockSizeBits);
+ this.ubi = new UBI(this,threefish.GetBlockSize());
+ }
+
+ /// <summary>
+ /// Creates a SkeinEngine as an exact copy of an existing instance.
+ /// </summary>
+ public SkeinEngine(SkeinEngine engine)
+ : this(engine.BlockSize * 8, engine.OutputSize * 8)
+ {
+ CopyIn(engine);
+ }
+
+ private void CopyIn(SkeinEngine engine)
+ {
+ this.ubi.Reset(engine.ubi);
+ this.chain = Arrays.Clone(engine.chain, this.chain);
+ this.initialState = Arrays.Clone(engine.initialState, this.initialState);
+ this.key = Arrays.Clone(engine.key, this.key);
+ this.preMessageParameters = Clone(engine.preMessageParameters, this.preMessageParameters);
+ this.postMessageParameters = Clone(engine.postMessageParameters, this.postMessageParameters);
+ }
+
+ private static Parameter[] Clone(Parameter[] data, Parameter[] existing)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+ if ((existing == null) || (existing.Length != data.Length))
+ {
+ existing = new Parameter[data.Length];
+ }
+ Array.Copy(data, 0, existing, 0, existing.Length);
+ return existing;
+ }
+
+ public IMemoable Copy()
+ {
+ return new SkeinEngine(this);
+ }
+
+ public void Reset(IMemoable other)
+ {
+ SkeinEngine s = (SkeinEngine)other;
+ if ((BlockSize != s.BlockSize) || (outputSizeBytes != s.outputSizeBytes))
+ {
+ throw new MemoableResetException("Incompatible parameters in provided SkeinEngine.");
+ }
+ CopyIn(s);
+ }
+
+ public int OutputSize
+ {
+ get { return outputSizeBytes; }
+ }
+
+ public int BlockSize
+ {
+ get { return threefish.GetBlockSize (); }
+ }
+
+ /// <summary>
+ /// Initialises the Skein engine with the provided parameters. See <see cref="Org.BouncyCastle.Crypto.Parameters.SkeinParameters"/> for
+ /// details on the parameterisation of the Skein hash function.
+ /// </summary>
+ /// <param name="parameters">the parameters to apply to this engine, or <code>null</code> to use no parameters.</param>
+ public void Init(SkeinParameters parameters)
+ {
+ this.chain = null;
+ this.key = null;
+ this.preMessageParameters = null;
+ this.postMessageParameters = null;
+
+ if (parameters != null)
+ {
+ byte[] key = parameters.GetKey();
+ if (key.Length < 16)
+ {
+ throw new ArgumentException("Skein key must be at least 128 bits.");
+ }
+ InitParams(parameters.GetParameters());
+ }
+ CreateInitialState();
+
+ // Initialise message block
+ UbiInit(PARAM_TYPE_MESSAGE);
+ }
+
+ private void InitParams(IDictionary parameters)
+ {
+ IEnumerator keys = parameters.Keys.GetEnumerator();
+ IList pre = Platform.CreateArrayList();
+ IList post = Platform.CreateArrayList();
+
+ while (keys.MoveNext())
+ {
+ int type = (int)keys.Current;
+ byte[] value = (byte[])parameters[type];
+
+ if (type == PARAM_TYPE_KEY)
+ {
+ this.key = value;
+ }
+ else if (type < PARAM_TYPE_MESSAGE)
+ {
+ pre.Add(new Parameter(type, value));
+ }
+ else
+ {
+ post.Add(new Parameter(type, value));
+ }
+ }
+ preMessageParameters = new Parameter[pre.Count];
+ pre.CopyTo(preMessageParameters, 0);
+ Array.Sort(preMessageParameters);
+
+ postMessageParameters = new Parameter[post.Count];
+ post.CopyTo(postMessageParameters, 0);
+ Array.Sort(postMessageParameters);
+ }
+
+ /**
+ * Calculate the initial (pre message block) chaining state.
+ */
+ private void CreateInitialState()
+ {
+ ulong[] precalc = (ulong[])INITIAL_STATES[VariantIdentifier(BlockSize, OutputSize)];
+ if ((key == null) && (precalc != null))
+ {
+ // Precalculated UBI(CFG)
+ chain = Arrays.Clone(precalc);
+ }
+ else
+ {
+ // Blank initial state
+ chain = new ulong[BlockSize / 8];
+
+ // Process key block
+ if (key != null)
+ {
+ UbiComplete(SkeinParameters.PARAM_TYPE_KEY, key);
+ }
+
+ // Process configuration block
+ UbiComplete(PARAM_TYPE_CONFIG, new Configuration(outputSizeBytes * 8).Bytes);
+ }
+
+ // Process additional pre-message parameters
+ if (preMessageParameters != null)
+ {
+ for (int i = 0; i < preMessageParameters.Length; i++)
+ {
+ Parameter param = preMessageParameters[i];
+ UbiComplete(param.Type, param.Value);
+ }
+ }
+ initialState = Arrays.Clone(chain);
+ }
+
+ /// <summary>
+ /// Reset the engine to the initial state (with the key and any pre-message parameters , ready to
+ /// accept message input.
+ /// </summary>
+ public void Reset()
+ {
+ Array.Copy(initialState, 0, chain, 0, chain.Length);
+
+ UbiInit(PARAM_TYPE_MESSAGE);
+ }
+
+ private void UbiComplete(int type, byte[] value)
+ {
+ UbiInit(type);
+ this.ubi.Update(value, 0, value.Length, chain);
+ UbiFinal();
+ }
+
+ private void UbiInit(int type)
+ {
+ this.ubi.Reset(type);
+ }
+
+ private void UbiFinal()
+ {
+ ubi.DoFinal(chain);
+ }
+
+ private void CheckInitialised()
+ {
+ if (this.ubi == null)
+ {
+ throw new ArgumentException("Skein engine is not initialised.");
+ }
+ }
+
+ public void Update(byte inByte)
+ {
+ singleByte[0] = inByte;
+ Update(singleByte, 0, 1);
+ }
+
+ public void Update(byte[] inBytes, int inOff, int len)
+ {
+ CheckInitialised();
+ ubi.Update(inBytes, inOff, len, chain);
+ }
+
+ public int DoFinal(byte[] outBytes, int outOff)
+ {
+ CheckInitialised();
+ if (outBytes.Length < (outOff + outputSizeBytes))
+ {
+ throw new DataLengthException("Output buffer is too short to hold output of " + outputSizeBytes + " bytes");
+ }
+
+ // Finalise message block
+ UbiFinal();
+
+ // Process additional post-message parameters
+ if (postMessageParameters != null)
+ {
+ for (int i = 0; i < postMessageParameters.Length; i++)
+ {
+ Parameter param = postMessageParameters[i];
+ UbiComplete(param.Type, param.Value);
+ }
+ }
+
+ // Perform the output transform
+ int blockSize = BlockSize;
+ int blocksRequired = ((outputSizeBytes + blockSize - 1) / blockSize);
+ for (int i = 0; i < blocksRequired; i++)
+ {
+ int toWrite = System.Math.Min(blockSize, outputSizeBytes - (i * blockSize));
+ Output((ulong)i, outBytes, outOff + (i * blockSize), toWrite);
+ }
+
+ Reset();
+
+ return outputSizeBytes;
+ }
+
+ private void Output(ulong outputSequence, byte[] outBytes, int outOff, int outputBytes)
+ {
+ byte[] currentBytes = new byte[8];
+ ThreefishEngine.WordToBytes(outputSequence, currentBytes, 0);
+
+ // Output is a sequence of UBI invocations all of which use and preserve the pre-output
+ // state
+ ulong[] outputWords = new ulong[chain.Length];
+ UbiInit(PARAM_TYPE_OUTPUT);
+ this.ubi.Update(currentBytes, 0, currentBytes.Length, outputWords);
+ ubi.DoFinal(outputWords);
+
+ int wordsRequired = ((outputBytes + 8 - 1) / 8);
+ for (int i = 0; i < wordsRequired; i++)
+ {
+ int toWrite = System.Math.Min(8, outputBytes - (i * 8));
+ if (toWrite == 8)
+ {
+ ThreefishEngine.WordToBytes(outputWords[i], outBytes, outOff + (i * 8));
+ }
+ else
+ {
+ ThreefishEngine.WordToBytes(outputWords[i], currentBytes, 0);
+ Array.Copy(currentBytes, 0, outBytes, outOff + (i * 8), toWrite);
+ }
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/crypto/src/crypto/digests/Sm3Digest.cs b/crypto/src/crypto/digests/Sm3Digest.cs
new file mode 100644
index 000000000..7a9e6db36
--- /dev/null
+++ b/crypto/src/crypto/digests/Sm3Digest.cs
@@ -0,0 +1,328 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Digests
+{
+
+ /// <summary>
+ /// Implementation of Chinese SM3 digest as described at
+ /// http://tools.ietf.org/html/draft-shen-sm3-hash-00
+ /// and at .... ( Chinese PDF )
+ /// </summary>
+ /// <remarks>
+ /// The specification says "process a bit stream",
+ /// but this is written to process bytes in blocks of 4,
+ /// meaning this will process 32-bit word groups.
+ /// But so do also most other digest specifications,
+ /// including the SHA-256 which was a origin for
+ /// this specification.
+ /// </remarks>
+ public class Sm3Digest
+ : GeneralDigest
+ {
+ private const int DIGEST_LENGTH = 32; // bytes
+ private const int BLOCK_SIZE = 64 / 4; // of 32 bit ints (16 ints)
+
+ private uint[] V = new uint[DIGEST_LENGTH / 4]; // in 32 bit ints (8 ints)
+ private uint[] inwords = new uint[BLOCK_SIZE];
+ private int xOff;
+
+ // Work-bufs used within processBlock()
+ private uint[] W = new uint[68];
+ private uint[] W1 = new uint[64];
+
+ // Round constant T for processBlock() which is 32 bit integer rolled left up to (63 MOD 32) bit positions.
+ private static readonly uint[] T = new uint[64];
+
+ static Sm3Digest()
+ {
+ for (int i = 0; i < 16; ++i)
+ {
+ uint t = 0x79CC4519;
+ T[i] = (t << i) | (t >> (32 - i));
+ }
+ for (int i = 16; i < 64; ++i)
+ {
+ int n = i % 32;
+ uint t = 0x7A879D8A;
+ T[i] = (t << n) | (t >> (32 - n));
+ }
+ }
+
+
+ /// <summary>
+ /// Standard constructor
+ /// </summary>
+ public Sm3Digest()
+ {
+ Reset();
+ }
+
+ /// <summary>
+ /// Copy constructor. This will copy the state of the provided
+ /// message digest.
+ /// </summary>
+ public Sm3Digest(Sm3Digest t)
+ : base(t)
+ {
+ CopyIn(t);
+ }
+
+ private void CopyIn(Sm3Digest t)
+ {
+ Array.Copy(t.V, 0, this.V, 0, this.V.Length);
+ Array.Copy(t.inwords, 0, this.inwords, 0, this.inwords.Length);
+ xOff = t.xOff;
+ }
+
+ public override string AlgorithmName
+ {
+ get { return "SM3"; }
+ }
+
+ public override int GetDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ public override IMemoable Copy()
+ {
+ return new Sm3Digest(this);
+ }
+
+ public override void Reset(IMemoable other)
+ {
+ Sm3Digest d = (Sm3Digest)other;
+
+ base.CopyIn(d);
+ CopyIn(d);
+ }
+
+ /// <summary>
+ /// reset the chaining variables
+ /// </summary>
+ public override void Reset()
+ {
+ base.Reset();
+
+ this.V[0] = 0x7380166F;
+ this.V[1] = 0x4914B2B9;
+ this.V[2] = 0x172442D7;
+ this.V[3] = 0xDA8A0600;
+ this.V[4] = 0xA96F30BC;
+ this.V[5] = 0x163138AA;
+ this.V[6] = 0xE38DEE4D;
+ this.V[7] = 0xB0FB0E4E;
+
+ this.xOff = 0;
+ }
+
+
+ public override int DoFinal(byte[] output, int outOff)
+ {
+ Finish();
+
+ Pack.UInt32_To_BE(this.V[0], output, outOff + 0);
+ Pack.UInt32_To_BE(this.V[1], output, outOff + 4);
+ Pack.UInt32_To_BE(this.V[2], output, outOff + 8);
+ Pack.UInt32_To_BE(this.V[3], output, outOff + 12);
+ Pack.UInt32_To_BE(this.V[4], output, outOff + 16);
+ Pack.UInt32_To_BE(this.V[5], output, outOff + 20);
+ Pack.UInt32_To_BE(this.V[6], output, outOff + 24);
+ Pack.UInt32_To_BE(this.V[7], output, outOff + 28);
+
+ Reset();
+
+ return DIGEST_LENGTH;
+ }
+
+
+ internal override void ProcessWord(byte[] input,
+ int inOff)
+ {
+ uint n = Pack.BE_To_UInt32(input, inOff);
+ this.inwords[this.xOff] = n;
+ ++this.xOff;
+
+ if (this.xOff >= 16)
+ {
+ ProcessBlock();
+ }
+ }
+
+ internal override void ProcessLength(long bitLength)
+ {
+ if (this.xOff > (BLOCK_SIZE - 2))
+ {
+ // xOff == 15 --> can't fit the 64 bit length field at tail..
+ this.inwords[this.xOff] = 0; // fill with zero
+ ++this.xOff;
+
+ ProcessBlock();
+ }
+ // Fill with zero words, until reach 2nd to last slot
+ while (this.xOff < (BLOCK_SIZE - 2))
+ {
+ this.inwords[this.xOff] = 0;
+ ++this.xOff;
+ }
+
+ // Store input data length in BITS
+ this.inwords[this.xOff++] = (uint)(bitLength >> 32);
+ this.inwords[this.xOff++] = (uint)(bitLength);
+ }
+
+ /*
+
+ 3.4.2. Constants
+
+
+ Tj = 79cc4519 when 0 < = j < = 15
+ Tj = 7a879d8a when 16 < = j < = 63
+
+ 3.4.3. Boolean function
+
+
+ FFj(X;Y;Z) = X XOR Y XOR Z when 0 < = j < = 15
+ = (X AND Y) OR (X AND Z) OR (Y AND Z) when 16 < = j < = 63
+
+ GGj(X;Y;Z) = X XOR Y XOR Z when 0 < = j < = 15
+ = (X AND Y) OR (NOT X AND Z) when 16 < = j < = 63
+
+ The X, Y, Z in the fomular are words!GBP
+
+ 3.4.4. Permutation function
+
+
+ P0(X) = X XOR (X <<< 9) XOR (X <<< 17) ## ROLL, not SHIFT
+ P1(X) = X XOR (X <<< 15) XOR (X <<< 23) ## ROLL, not SHIFT
+
+ The X in the fomular are a word.
+
+ ----------
+
+ Each ROLL converted to Java expression:
+
+ ROLL 9 : ((x << 9) | (x >> (32-9))))
+ ROLL 17 : ((x << 17) | (x >> (32-17)))
+ ROLL 15 : ((x << 15) | (x >> (32-15)))
+ ROLL 23 : ((x << 23) | (x >> (32-23)))
+
+ */
+
+ private uint P0(uint x)
+ {
+ uint r9 = ((x << 9) | (x >> (32 - 9)));
+ uint r17 = ((x << 17) | (x >> (32 - 17)));
+ return (x ^ r9 ^ r17);
+ }
+
+ private uint P1(uint x)
+ {
+ uint r15 = ((x << 15) | (x >> (32 - 15)));
+ uint r23 = ((x << 23) | (x >> (32 - 23)));
+ return (x ^ r15 ^ r23);
+ }
+
+ private uint FF0(uint x, uint y, uint z)
+ {
+ return (x ^ y ^ z);
+ }
+
+ private uint FF1(uint x, uint y, uint z)
+ {
+ return ((x & y) | (x & z) | (y & z));
+ }
+
+ private uint GG0(uint x, uint y, uint z)
+ {
+ return (x ^ y ^ z);
+ }
+
+ private uint GG1(uint x, uint y, uint z)
+ {
+ return ((x & y) | ((~x) & z));
+ }
+
+
+ internal override void ProcessBlock()
+ {
+ for (int j = 0; j < 16; ++j)
+ {
+ this.W[j] = this.inwords[j];
+ }
+ for (int j = 16; j < 68; ++j)
+ {
+ uint wj3 = this.W[j - 3];
+ uint r15 = ((wj3 << 15) | (wj3 >> (32 - 15)));
+ uint wj13 = this.W[j - 13];
+ uint r7 = ((wj13 << 7) | (wj13 >> (32 - 7)));
+ this.W[j] = P1(this.W[j - 16] ^ this.W[j - 9] ^ r15) ^ r7 ^ this.W[j - 6];
+ }
+ for (int j = 0; j < 64; ++j)
+ {
+ this.W1[j] = this.W[j] ^ this.W[j + 4];
+ }
+
+ uint A = this.V[0];
+ uint B = this.V[1];
+ uint C = this.V[2];
+ uint D = this.V[3];
+ uint E = this.V[4];
+ uint F = this.V[5];
+ uint G = this.V[6];
+ uint H = this.V[7];
+
+
+ for (int j = 0; j < 16; ++j)
+ {
+ uint a12 = ((A << 12) | (A >> (32 - 12)));
+ uint s1_ = a12 + E + T[j];
+ uint SS1 = ((s1_ << 7) | (s1_ >> (32 - 7)));
+ uint SS2 = SS1 ^ a12;
+ uint TT1 = FF0(A, B, C) + D + SS2 + this.W1[j];
+ uint TT2 = GG0(E, F, G) + H + SS1 + this.W[j];
+ D = C;
+ C = ((B << 9) | (B >> (32 - 9)));
+ B = A;
+ A = TT1;
+ H = G;
+ G = ((F << 19) | (F >> (32 - 19)));
+ F = E;
+ E = P0(TT2);
+ }
+
+ // Different FF,GG functions on rounds 16..63
+ for (int j = 16; j < 64; ++j)
+ {
+ uint a12 = ((A << 12) | (A >> (32 - 12)));
+ uint s1_ = a12 + E + T[j];
+ uint SS1 = ((s1_ << 7) | (s1_ >> (32 - 7)));
+ uint SS2 = SS1 ^ a12;
+ uint TT1 = FF1(A, B, C) + D + SS2 + this.W1[j];
+ uint TT2 = GG1(E, F, G) + H + SS1 + this.W[j];
+ D = C;
+ C = ((B << 9) | (B >> (32 - 9)));
+ B = A;
+ A = TT1;
+ H = G;
+ G = ((F << 19) | (F >> (32 - 19)));
+ F = E;
+ E = P0(TT2);
+ }
+
+ this.V[0] ^= A;
+ this.V[1] ^= B;
+ this.V[2] ^= C;
+ this.V[3] ^= D;
+ this.V[4] ^= E;
+ this.V[5] ^= F;
+ this.V[6] ^= G;
+ this.V[7] ^= H;
+
+ this.xOff = 0;
+ }
+ }
+}
\ No newline at end of file
diff --git a/crypto/src/crypto/digests/TigerDigest.cs b/crypto/src/crypto/digests/TigerDigest.cs
index b8c9a7664..059232de0 100644
--- a/crypto/src/crypto/digests/TigerDigest.cs
+++ b/crypto/src/crypto/digests/TigerDigest.cs
@@ -1,5 +1,7 @@
using System;
+
using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Digests
{
@@ -9,7 +11,7 @@ namespace Org.BouncyCastle.Crypto.Digests
* http://www.cs.technion.ac.il/~biham/Reports/Tiger</a>
*/
public class TigerDigest
- : IDigest
+ : IDigest, IMemoable
{
private const int MyByteLength = 64;
@@ -571,17 +573,7 @@ namespace Org.BouncyCastle.Crypto.Digests
*/
public TigerDigest(TigerDigest t)
{
- a = t.a;
- b = t.b;
- c = t.c;
-
- Array.Copy(t.x, 0, x, 0, t.x.Length);
- xOff = t.xOff;
-
- Array.Copy(t.Buffer, 0, Buffer, 0, t.Buffer.Length);
- bOff = t.bOff;
-
- byteCount = t.byteCount;
+ Reset(t);
}
public string AlgorithmName
@@ -864,5 +856,28 @@ namespace Org.BouncyCastle.Crypto.Digests
byteCount = 0;
}
- }
+
+ public IMemoable Copy()
+ {
+ return new TigerDigest(this);
+ }
+
+ public void Reset(IMemoable other)
+ {
+ TigerDigest t = (TigerDigest)other;
+
+ a = t.a;
+ b = t.b;
+ c = t.c;
+
+ Array.Copy(t.x, 0, x, 0, t.x.Length);
+ xOff = t.xOff;
+
+ Array.Copy(t.Buffer, 0, Buffer, 0, t.Buffer.Length);
+ bOff = t.bOff;
+
+ byteCount = t.byteCount;
+ }
+
+ }
}
diff --git a/crypto/src/crypto/digests/WhirlpoolDigest.cs b/crypto/src/crypto/digests/WhirlpoolDigest.cs
index df83f4508..55b71205e 100644
--- a/crypto/src/crypto/digests/WhirlpoolDigest.cs
+++ b/crypto/src/crypto/digests/WhirlpoolDigest.cs
@@ -1,6 +1,7 @@
using System;
using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Digests
{
@@ -9,7 +10,8 @@ namespace Org.BouncyCastle.Crypto.Digests
* and Rijmen.
*
*/
- public sealed class WhirlpoolDigest : IDigest
+ public sealed class WhirlpoolDigest
+ : IDigest, IMemoable
{
private const int BYTE_LENGTH = 64;
@@ -149,19 +151,7 @@ namespace Org.BouncyCastle.Crypto.Digests
*/
public WhirlpoolDigest(WhirlpoolDigest originalDigest)
{
- Array.Copy(originalDigest._rc, 0, _rc, 0, _rc.Length);
-
- Array.Copy(originalDigest._buffer, 0, _buffer, 0, _buffer.Length);
-
- this._bufferPos = originalDigest._bufferPos;
- Array.Copy(originalDigest._bitCount, 0, _bitCount, 0, _bitCount.Length);
-
- // -- internal hash state --
- Array.Copy(originalDigest._hash, 0, _hash, 0, _hash.Length);
- Array.Copy(originalDigest._K, 0, _K, 0, _K.Length);
- Array.Copy(originalDigest._L, 0, _L, 0, _L.Length);
- Array.Copy(originalDigest._block, 0, _block, 0, _block.Length);
- Array.Copy(originalDigest._state, 0, _state, 0, _state.Length);
+ Reset(originalDigest);
}
public string AlgorithmName
@@ -393,5 +383,31 @@ namespace Org.BouncyCastle.Crypto.Digests
{
return BYTE_LENGTH;
}
+
+ public IMemoable Copy()
+ {
+ return new WhirlpoolDigest(this);
+ }
+
+ public void Reset(IMemoable other)
+ {
+ WhirlpoolDigest originalDigest = (WhirlpoolDigest)other;
+
+ Array.Copy(originalDigest._rc, 0, _rc, 0, _rc.Length);
+
+ Array.Copy(originalDigest._buffer, 0, _buffer, 0, _buffer.Length);
+
+ this._bufferPos = originalDigest._bufferPos;
+ Array.Copy(originalDigest._bitCount, 0, _bitCount, 0, _bitCount.Length);
+
+ // -- internal hash state --
+ Array.Copy(originalDigest._hash, 0, _hash, 0, _hash.Length);
+ Array.Copy(originalDigest._K, 0, _K, 0, _K.Length);
+ Array.Copy(originalDigest._L, 0, _L, 0, _L.Length);
+ Array.Copy(originalDigest._block, 0, _block, 0, _block.Length);
+ Array.Copy(originalDigest._state, 0, _state, 0, _state.Length);
+ }
+
+
}
}
diff --git a/crypto/src/crypto/engines/ThreefishEngine.cs b/crypto/src/crypto/engines/ThreefishEngine.cs
new file mode 100644
index 000000000..3d4ee8835
--- /dev/null
+++ b/crypto/src/crypto/engines/ThreefishEngine.cs
@@ -0,0 +1,1491 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+
+ /// <summary>
+ /// Implementation of the Threefish tweakable large block cipher in 256, 512 and 1024 bit block
+ /// sizes.
+ /// </summary>
+ /// <remarks>
+ /// This is the 1.3 version of Threefish defined in the Skein hash function submission to the NIST
+ /// SHA-3 competition in October 2010.
+ /// <p/>
+ /// Threefish was designed by Niels Ferguson - Stefan Lucks - Bruce Schneier - Doug Whiting - Mihir
+ /// Bellare - Tadayoshi Kohno - Jon Callas - Jesse Walker.
+ /// <p/>
+ /// This implementation inlines all round functions, unrolls 8 rounds, and uses 1.2k of static tables
+ /// to speed up key schedule injection. <br>
+ /// 2 x block size state is retained by each cipher instance.
+ /// </remarks>
+ public class ThreefishEngine
+ : IBlockCipher
+ {
+ /// <summary>
+ /// 256 bit block size - Threefish-256
+ /// </summary>
+ public const int BLOCKSIZE_256 = 256;
+ /// <summary>
+ /// 512 bit block size - Threefish-512
+ /// </summary>
+ public const int BLOCKSIZE_512 = 512;
+ /// <summary>
+ /// 1024 bit block size - Threefish-1024
+ /// </summary>
+ public const int BLOCKSIZE_1024 = 1024;
+
+ /**
+ * Size of the tweak in bytes (always 128 bit/16 bytes)
+ */
+ private const int TWEAK_SIZE_BYTES = 16;
+ private const int TWEAK_SIZE_WORDS = TWEAK_SIZE_BYTES / 8;
+
+ /**
+ * Rounds in Threefish-256
+ */
+ private const int ROUNDS_256 = 72;
+ /**
+ * Rounds in Threefish-512
+ */
+ private const int ROUNDS_512 = 72;
+ /**
+ * Rounds in Threefish-1024
+ */
+ private const int ROUNDS_1024 = 80;
+
+ /**
+ * Max rounds of any of the variants
+ */
+ private const int MAX_ROUNDS = ROUNDS_1024;
+
+ /**
+ * Key schedule parity constant
+ */
+ private const ulong C_240 = 0x1BD11BDAA9FC1A22L;
+
+ /* Pre-calculated modulo arithmetic tables for key schedule lookups */
+ private static readonly int[] MOD9 = new int[MAX_ROUNDS];
+ private static readonly int[] MOD17 = new int[MOD9.Length];
+ private static readonly int[] MOD5 = new int[MOD9.Length];
+ private static readonly int[] MOD3 = new int[MOD9.Length];
+
+ static ThreefishEngine()
+ {
+ for (int i = 0; i < MOD9.Length; i++)
+ {
+ MOD17[i] = i % 17;
+ MOD9[i] = i % 9;
+ MOD5[i] = i % 5;
+ MOD3[i] = i % 3;
+ }
+ }
+
+ /**
+ * Block size in bytes
+ */
+ private readonly int blocksizeBytes;
+
+ /**
+ * Block size in 64 bit words
+ */
+ private readonly int blocksizeWords;
+
+ /**
+ * Buffer for byte oriented processBytes to call internal word API
+ */
+ private readonly ulong[] currentBlock;
+
+ /**
+ * Tweak bytes (2 byte t1,t2, calculated t3 and repeat of t1,t2 for modulo free lookup
+ */
+ private readonly ulong[] t = new ulong[5];
+
+ /**
+ * Key schedule words
+ */
+ private readonly ulong[] kw;
+
+ /**
+ * The internal cipher implementation (varies by blocksize)
+ */
+ private readonly ThreefishCipher cipher;
+
+ private bool forEncryption;
+
+ /// <summary>
+ /// Constructs a new Threefish cipher, with a specified block size.
+ /// </summary>
+ /// <param name="blocksizeBits">the block size in bits, one of <see cref="BLOCKSIZE_256"/>, <see cref="BLOCKSIZE_512"/>,
+ /// <see cref="BLOCKSIZE_1024"/> .</param>
+ public ThreefishEngine(int blocksizeBits)
+ {
+ this.blocksizeBytes = (blocksizeBits / 8);
+ this.blocksizeWords = (this.blocksizeBytes / 8);
+ this.currentBlock = new ulong[blocksizeWords];
+
+ /*
+ * Provide room for original key words, extended key word and repeat of key words for modulo
+ * free lookup of key schedule words.
+ */
+ this.kw = new ulong[2 * blocksizeWords + 1];
+
+ switch (blocksizeBits)
+ {
+ case BLOCKSIZE_256:
+ cipher = new Threefish256Cipher(kw, t);
+ break;
+ case BLOCKSIZE_512:
+ cipher = new Threefish512Cipher(kw, t);
+ break;
+ case BLOCKSIZE_1024:
+ cipher = new Threefish1024Cipher(kw, t);
+ break;
+ default:
+ throw new ArgumentException(
+ "Invalid blocksize - Threefish is defined with block size of 256, 512, or 1024 bits");
+ }
+ }
+
+ /// <summary>
+ /// Initialise the engine.
+ /// </summary>
+ /// <param name="forEncryption">Initialise for encryption if true, for decryption if false.</param>
+ /// <param name="parameters">an instance of <see cref="TweakableBlockCipherParameters"/> or <see cref="KeyParameter"/> (to
+ /// use a 0 tweak)</param>
+ public void Init(bool forEncryption, ICipherParameters parameters)
+ {
+ byte[] keyBytes;
+ byte[] tweakBytes;
+
+ if (parameters is TweakableBlockCipherParameters)
+ {
+ TweakableBlockCipherParameters tParams = (TweakableBlockCipherParameters)parameters;
+ keyBytes = tParams.Key.GetKey();
+ tweakBytes = tParams.Tweak;
+ }
+ else if (parameters is KeyParameter)
+ {
+ keyBytes = ((KeyParameter)parameters).GetKey();
+ tweakBytes = null;
+ }
+ else
+ {
+ throw new ArgumentException("Invalid parameter passed to Threefish init - "
+ + parameters.GetType().Name);
+ }
+
+ ulong[] keyWords = null;
+ ulong[] tweakWords = null;
+
+ if (keyBytes != null)
+ {
+ if (keyBytes.Length != this.blocksizeBytes)
+ {
+ throw new ArgumentException("Threefish key must be same size as block (" + blocksizeBytes
+ + " bytes)");
+ }
+ keyWords = new ulong[blocksizeWords];
+ for (int i = 0; i < keyWords.Length; i++)
+ {
+ keyWords[i] = BytesToWord(keyBytes, i * 8);
+ }
+ }
+ if (tweakBytes != null)
+ {
+ if (tweakBytes.Length != TWEAK_SIZE_BYTES)
+ {
+ throw new ArgumentException("Threefish tweak must be " + TWEAK_SIZE_BYTES + " bytes");
+ }
+ tweakWords = new ulong[]{BytesToWord(tweakBytes, 0), BytesToWord(tweakBytes, 8)};
+ }
+ Init(forEncryption, keyWords, tweakWords);
+ }
+
+ /// <summary>
+ /// Initialise the engine, specifying the key and tweak directly.
+ /// </summary>
+ /// <param name="forEncryption">the cipher mode.</param>
+ /// <param name="key">the words of the key, or <code>null</code> to use the current key.</param>
+ /// <param name="tweak">the 2 word (128 bit) tweak, or <code>null</code> to use the current tweak.</param>
+ internal void Init(bool forEncryption, ulong[] key, ulong[] tweak)
+ {
+ this.forEncryption = forEncryption;
+ if (key != null)
+ {
+ SetKey(key);
+ }
+ if (tweak != null)
+ {
+ SetTweak(tweak);
+ }
+ }
+
+ private void SetKey(ulong[] key)
+ {
+ if (key.Length != this.blocksizeWords)
+ {
+ throw new ArgumentException("Threefish key must be same size as block (" + blocksizeWords
+ + " words)");
+ }
+
+ /*
+ * Full subkey schedule is deferred to execution to avoid per cipher overhead (10k for 512,
+ * 20k for 1024).
+ *
+ * Key and tweak word sequences are repeated, and static MOD17/MOD9/MOD5/MOD3 calculations
+ * used, to avoid expensive mod computations during cipher operation.
+ */
+
+ ulong knw = C_240;
+ for (int i = 0; i < blocksizeWords; i++)
+ {
+ kw[i] = key[i];
+ knw = knw ^ kw[i];
+ }
+ kw[blocksizeWords] = knw;
+ Array.Copy(kw, 0, kw, blocksizeWords + 1, blocksizeWords);
+ }
+
+ private void SetTweak(ulong[] tweak)
+ {
+ if (tweak.Length != TWEAK_SIZE_WORDS)
+ {
+ throw new ArgumentException("Tweak must be " + TWEAK_SIZE_WORDS + " words.");
+ }
+
+ /*
+ * Tweak schedule partially repeated to avoid mod computations during cipher operation
+ */
+ t[0] = tweak[0];
+ t[1] = tweak[1];
+ t[2] = t[0] ^ t[1];
+ t[3] = t[0];
+ t[4] = t[1];
+ }
+
+ public string AlgorithmName
+ {
+ get { return "Threefish-" + (blocksizeBytes * 8); }
+ }
+
+ public bool IsPartialBlockOkay
+ {
+ get { return false; }
+ }
+
+ public int GetBlockSize()
+ {
+ return blocksizeBytes;
+ }
+
+ public void Reset()
+ {
+ }
+
+ public int ProcessBlock(byte[] inBytes, int inOff, byte[] outBytes, int outOff)
+ {
+ if ((outOff + blocksizeBytes) > outBytes.Length)
+ {
+ throw new DataLengthException("Output buffer too short");
+ }
+
+ if ((inOff + blocksizeBytes) > inBytes.Length)
+ {
+ throw new DataLengthException("Input buffer too short");
+ }
+
+ for (int i = 0; i < blocksizeBytes; i += 8)
+ {
+ currentBlock[i >> 3] = BytesToWord(inBytes, inOff + i);
+ }
+ ProcessBlock(this.currentBlock, this.currentBlock);
+ for (int i = 0; i < blocksizeBytes; i += 8)
+ {
+ WordToBytes(this.currentBlock[i >> 3], outBytes, outOff + i);
+ }
+
+ return blocksizeBytes;
+ }
+
+ /// <summary>
+ /// Process a block of data represented as 64 bit words.
+ /// </summary>
+ /// <returns>the number of 8 byte words processed (which will be the same as the block size).</returns>
+ /// <param name="inWords">a block sized buffer of words to process.</param>
+ /// <param name="outWords">a block sized buffer of words to receive the output of the operation.</param>
+ /// <exception cref="DataLengthException">if either the input or output is not block sized</exception>
+ /// <exception cref="InvalidOperationException">if this engine is not initialised</exception>
+ internal int ProcessBlock(ulong[] inWords, ulong[] outWords)
+ {
+ if (kw[blocksizeWords] == 0)
+ {
+ throw new InvalidOperationException("Threefish engine not initialised");
+ }
+
+ if (inWords.Length != blocksizeWords)
+ {
+ throw new DataLengthException("Input buffer too short");
+ }
+ if (outWords.Length != blocksizeWords)
+ {
+ throw new DataLengthException("Output buffer too short");
+ }
+
+ if (forEncryption)
+ {
+ cipher.EncryptBlock(inWords, outWords);
+ }
+ else
+ {
+ cipher.DecryptBlock(inWords, outWords);
+ }
+
+ return blocksizeWords;
+ }
+
+ /// <summary>
+ /// Read a single 64 bit word from input in LSB first order.
+ /// </summary>
+ internal static ulong BytesToWord(byte[] bytes, int off)
+ {
+ if ((off + 8) > bytes.Length)
+ {
+ // Help the JIT avoid index checks
+ throw new ArgumentException();
+ }
+
+ ulong word = 0;
+ int index = off;
+
+ word = (bytes[index++] & 0xffUL);
+ word |= (bytes[index++] & 0xffUL) << 8;
+ word |= (bytes[index++] & 0xffUL) << 16;
+ word |= (bytes[index++] & 0xffUL) << 24;
+ word |= (bytes[index++] & 0xffUL) << 32;
+ word |= (bytes[index++] & 0xffUL) << 40;
+ word |= (bytes[index++] & 0xffUL) << 48;
+ word |= (bytes[index++] & 0xffUL) << 56;
+
+ return word;
+ }
+
+ /// <summary>
+ /// Write a 64 bit word to output in LSB first order.
+ /// </summary>
+ internal static void WordToBytes(ulong word, byte[] bytes, int off)
+ {
+ if ((off + 8) > bytes.Length)
+ {
+ // Help the JIT avoid index checks
+ throw new ArgumentException();
+ }
+ int index = off;
+
+ bytes[index++] = (byte)word;
+ bytes[index++] = (byte)(word >> 8);
+ bytes[index++] = (byte)(word >> 16);
+ bytes[index++] = (byte)(word >> 24);
+ bytes[index++] = (byte)(word >> 32);
+ bytes[index++] = (byte)(word >> 40);
+ bytes[index++] = (byte)(word >> 48);
+ bytes[index++] = (byte)(word >> 56);
+ }
+
+ /**
+ * Rotate left + xor part of the mix operation.
+ */
+ private static ulong RotlXor(ulong x, int n, ulong xor)
+ {
+ return ((x << n) | (x >> (64 - n))) ^ xor;
+ }
+
+ /**
+ * Rotate xor + rotate right part of the unmix operation.
+ */
+ private static ulong XorRotr(ulong x, int n, ulong xor)
+ {
+ ulong xored = x ^ xor;
+ return (xored >> n) | (xored << (64 - n));
+ }
+
+ private abstract class ThreefishCipher
+ {
+ /**
+ * The extended + repeated tweak words
+ */
+ protected readonly ulong[] t;
+ /**
+ * The extended + repeated key words
+ */
+ protected readonly ulong[] kw;
+
+ protected ThreefishCipher(ulong[] kw, ulong[] t)
+ {
+ this.kw = kw;
+ this.t = t;
+ }
+
+ internal abstract void EncryptBlock(ulong[] block, ulong[] outWords);
+
+ internal abstract void DecryptBlock(ulong[] block, ulong[] outWords);
+
+ }
+
+ private sealed class Threefish256Cipher
+ : ThreefishCipher
+ {
+ /**
+ * Mix rotation constants defined in Skein 1.3 specification
+ */
+ private const int ROTATION_0_0 = 14, ROTATION_0_1 = 16;
+ private const int ROTATION_1_0 = 52, ROTATION_1_1 = 57;
+ private const int ROTATION_2_0 = 23, ROTATION_2_1 = 40;
+ private const int ROTATION_3_0 = 5, ROTATION_3_1 = 37;
+
+ private const int ROTATION_4_0 = 25, ROTATION_4_1 = 33;
+ private const int ROTATION_5_0 = 46, ROTATION_5_1 = 12;
+ private const int ROTATION_6_0 = 58, ROTATION_6_1 = 22;
+ private const int ROTATION_7_0 = 32, ROTATION_7_1 = 32;
+
+ public Threefish256Cipher(ulong[] kw, ulong[] t)
+ : base(kw, t)
+ {
+ }
+
+ internal override void EncryptBlock(ulong[] block, ulong[] outWords)
+ {
+ ulong[] kw = this.kw;
+ ulong[] t = this.t;
+ int[] mod5 = MOD5;
+ int[] mod3 = MOD3;
+
+ /* Help the JIT avoid index bounds checks */
+ if (kw.Length != 9)
+ {
+ throw new ArgumentException();
+ }
+ if (t.Length != 5)
+ {
+ throw new ArgumentException();
+ }
+
+ /*
+ * Read 4 words of plaintext data, not using arrays for cipher state
+ */
+ ulong b0 = block[0];
+ ulong b1 = block[1];
+ ulong b2 = block[2];
+ ulong b3 = block[3];
+
+ /*
+ * First subkey injection.
+ */
+ b0 += kw[0];
+ b1 += kw[1] + t[0];
+ b2 += kw[2] + t[1];
+ b3 += kw[3];
+
+ /*
+ * Rounds loop, unrolled to 8 rounds per iteration.
+ *
+ * Unrolling to multiples of 4 avoids the mod 4 check for key injection, and allows
+ * inlining of the permutations, which cycle every of 2 rounds (avoiding array
+ * index/lookup).
+ *
+ * Unrolling to multiples of 8 avoids the mod 8 rotation constant lookup, and allows
+ * inlining constant rotation values (avoiding array index/lookup).
+ */
+
+ for (int d = 1; d < (ROUNDS_256 / 4); d += 2)
+ {
+ int dm5 = mod5[d];
+ int dm3 = mod3[d];
+
+ /*
+ * 4 rounds of mix and permute.
+ *
+ * Permute schedule has a 2 round cycle, so permutes are inlined in the mix
+ * operations in each 4 round block.
+ */
+ b1 = RotlXor(b1, ROTATION_0_0, b0 += b1);
+ b3 = RotlXor(b3, ROTATION_0_1, b2 += b3);
+
+ b3 = RotlXor(b3, ROTATION_1_0, b0 += b3);
+ b1 = RotlXor(b1, ROTATION_1_1, b2 += b1);
+
+ b1 = RotlXor(b1, ROTATION_2_0, b0 += b1);
+ b3 = RotlXor(b3, ROTATION_2_1, b2 += b3);
+
+ b3 = RotlXor(b3, ROTATION_3_0, b0 += b3);
+ b1 = RotlXor(b1, ROTATION_3_1, b2 += b1);
+
+ /*
+ * Subkey injection for first 4 rounds.
+ */
+ b0 += kw[dm5];
+ b1 += kw[dm5 + 1] + t[dm3];
+ b2 += kw[dm5 + 2] + t[dm3 + 1];
+ b3 += kw[dm5 + 3] + (uint)d;
+
+ /*
+ * 4 more rounds of mix/permute
+ */
+ b1 = RotlXor(b1, ROTATION_4_0, b0 += b1);
+ b3 = RotlXor(b3, ROTATION_4_1, b2 += b3);
+
+ b3 = RotlXor(b3, ROTATION_5_0, b0 += b3);
+ b1 = RotlXor(b1, ROTATION_5_1, b2 += b1);
+
+ b1 = RotlXor(b1, ROTATION_6_0, b0 += b1);
+ b3 = RotlXor(b3, ROTATION_6_1, b2 += b3);
+
+ b3 = RotlXor(b3, ROTATION_7_0, b0 += b3);
+ b1 = RotlXor(b1, ROTATION_7_1, b2 += b1);
+
+ /*
+ * Subkey injection for next 4 rounds.
+ */
+ b0 += kw[dm5 + 1];
+ b1 += kw[dm5 + 2] + t[dm3 + 1];
+ b2 += kw[dm5 + 3] + t[dm3 + 2];
+ b3 += kw[dm5 + 4] + (uint)d + 1;
+ }
+
+ /*
+ * Output cipher state.
+ */
+ outWords[0] = b0;
+ outWords[1] = b1;
+ outWords[2] = b2;
+ outWords[3] = b3;
+ }
+
+ internal override void DecryptBlock(ulong[] block, ulong[] state)
+ {
+ ulong[] kw = this.kw;
+ ulong[] t = this.t;
+ int[] mod5 = MOD5;
+ int[] mod3 = MOD3;
+
+ /* Help the JIT avoid index bounds checks */
+ if (kw.Length != 9)
+ {
+ throw new ArgumentException();
+ }
+ if (t.Length != 5)
+ {
+ throw new ArgumentException();
+ }
+
+ ulong b0 = block[0];
+ ulong b1 = block[1];
+ ulong b2 = block[2];
+ ulong b3 = block[3];
+
+ for (int d = (ROUNDS_256 / 4) - 1; d >= 1; d -= 2)
+ {
+ int dm5 = mod5[d];
+ int dm3 = mod3[d];
+
+ /* Reverse key injection for second 4 rounds */
+ b0 -= kw[dm5 + 1];
+ b1 -= kw[dm5 + 2] + t[dm3 + 1];
+ b2 -= kw[dm5 + 3] + t[dm3 + 2];
+ b3 -= kw[dm5 + 4] + (uint)d + 1;
+
+ /* Reverse second 4 mix/permute rounds */
+
+ b3 = XorRotr(b3, ROTATION_7_0, b0);
+ b0 -= b3;
+ b1 = XorRotr(b1, ROTATION_7_1, b2);
+ b2 -= b1;
+
+ b1 = XorRotr(b1, ROTATION_6_0, b0);
+ b0 -= b1;
+ b3 = XorRotr(b3, ROTATION_6_1, b2);
+ b2 -= b3;
+
+ b3 = XorRotr(b3, ROTATION_5_0, b0);
+ b0 -= b3;
+ b1 = XorRotr(b1, ROTATION_5_1, b2);
+ b2 -= b1;
+
+ b1 = XorRotr(b1, ROTATION_4_0, b0);
+ b0 -= b1;
+ b3 = XorRotr(b3, ROTATION_4_1, b2);
+ b2 -= b3;
+
+ /* Reverse key injection for first 4 rounds */
+ b0 -= kw[dm5];
+ b1 -= kw[dm5 + 1] + t[dm3];
+ b2 -= kw[dm5 + 2] + t[dm3 + 1];
+ b3 -= kw[dm5 + 3] + (uint)d;
+
+ /* Reverse first 4 mix/permute rounds */
+ b3 = XorRotr(b3, ROTATION_3_0, b0);
+ b0 -= b3;
+ b1 = XorRotr(b1, ROTATION_3_1, b2);
+ b2 -= b1;
+
+ b1 = XorRotr(b1, ROTATION_2_0, b0);
+ b0 -= b1;
+ b3 = XorRotr(b3, ROTATION_2_1, b2);
+ b2 -= b3;
+
+ b3 = XorRotr(b3, ROTATION_1_0, b0);
+ b0 -= b3;
+ b1 = XorRotr(b1, ROTATION_1_1, b2);
+ b2 -= b1;
+
+ b1 = XorRotr(b1, ROTATION_0_0, b0);
+ b0 -= b1;
+ b3 = XorRotr(b3, ROTATION_0_1, b2);
+ b2 -= b3;
+ }
+
+ /*
+ * First subkey uninjection.
+ */
+ b0 -= kw[0];
+ b1 -= kw[1] + t[0];
+ b2 -= kw[2] + t[1];
+ b3 -= kw[3];
+
+ /*
+ * Output cipher state.
+ */
+ state[0] = b0;
+ state[1] = b1;
+ state[2] = b2;
+ state[3] = b3;
+ }
+
+ }
+
+ private sealed class Threefish512Cipher
+ : ThreefishCipher
+ {
+ /**
+ * Mix rotation constants defined in Skein 1.3 specification
+ */
+ private const int ROTATION_0_0 = 46, ROTATION_0_1 = 36, ROTATION_0_2 = 19, ROTATION_0_3 = 37;
+ private const int ROTATION_1_0 = 33, ROTATION_1_1 = 27, ROTATION_1_2 = 14, ROTATION_1_3 = 42;
+ private const int ROTATION_2_0 = 17, ROTATION_2_1 = 49, ROTATION_2_2 = 36, ROTATION_2_3 = 39;
+ private const int ROTATION_3_0 = 44, ROTATION_3_1 = 9, ROTATION_3_2 = 54, ROTATION_3_3 = 56;
+
+ private const int ROTATION_4_0 = 39, ROTATION_4_1 = 30, ROTATION_4_2 = 34, ROTATION_4_3 = 24;
+ private const int ROTATION_5_0 = 13, ROTATION_5_1 = 50, ROTATION_5_2 = 10, ROTATION_5_3 = 17;
+ private const int ROTATION_6_0 = 25, ROTATION_6_1 = 29, ROTATION_6_2 = 39, ROTATION_6_3 = 43;
+ private const int ROTATION_7_0 = 8, ROTATION_7_1 = 35, ROTATION_7_2 = 56, ROTATION_7_3 = 22;
+
+ internal Threefish512Cipher(ulong[] kw, ulong[] t)
+ : base(kw, t)
+ {
+ }
+
+ internal override void EncryptBlock(ulong[] block, ulong[] outWords)
+ {
+ ulong[] kw = this.kw;
+ ulong[] t = this.t;
+ int[] mod9 = MOD9;
+ int[] mod3 = MOD3;
+
+ /* Help the JIT avoid index bounds checks */
+ if (kw.Length != 17)
+ {
+ throw new ArgumentException();
+ }
+ if (t.Length != 5)
+ {
+ throw new ArgumentException();
+ }
+
+ /*
+ * Read 8 words of plaintext data, not using arrays for cipher state
+ */
+ ulong b0 = block[0];
+ ulong b1 = block[1];
+ ulong b2 = block[2];
+ ulong b3 = block[3];
+ ulong b4 = block[4];
+ ulong b5 = block[5];
+ ulong b6 = block[6];
+ ulong b7 = block[7];
+
+ /*
+ * First subkey injection.
+ */
+ b0 += kw[0];
+ b1 += kw[1];
+ b2 += kw[2];
+ b3 += kw[3];
+ b4 += kw[4];
+ b5 += kw[5] + t[0];
+ b6 += kw[6] + t[1];
+ b7 += kw[7];
+
+ /*
+ * Rounds loop, unrolled to 8 rounds per iteration.
+ *
+ * Unrolling to multiples of 4 avoids the mod 4 check for key injection, and allows
+ * inlining of the permutations, which cycle every of 4 rounds (avoiding array
+ * index/lookup).
+ *
+ * Unrolling to multiples of 8 avoids the mod 8 rotation constant lookup, and allows
+ * inlining constant rotation values (avoiding array index/lookup).
+ */
+
+ for (int d = 1; d < (ROUNDS_512 / 4); d += 2)
+ {
+ int dm9 = mod9[d];
+ int dm3 = mod3[d];
+
+ /*
+ * 4 rounds of mix and permute.
+ *
+ * Permute schedule has a 4 round cycle, so permutes are inlined in the mix
+ * operations in each 4 round block.
+ */
+ b1 = RotlXor(b1, ROTATION_0_0, b0 += b1);
+ b3 = RotlXor(b3, ROTATION_0_1, b2 += b3);
+ b5 = RotlXor(b5, ROTATION_0_2, b4 += b5);
+ b7 = RotlXor(b7, ROTATION_0_3, b6 += b7);
+
+ b1 = RotlXor(b1, ROTATION_1_0, b2 += b1);
+ b7 = RotlXor(b7, ROTATION_1_1, b4 += b7);
+ b5 = RotlXor(b5, ROTATION_1_2, b6 += b5);
+ b3 = RotlXor(b3, ROTATION_1_3, b0 += b3);
+
+ b1 = RotlXor(b1, ROTATION_2_0, b4 += b1);
+ b3 = RotlXor(b3, ROTATION_2_1, b6 += b3);
+ b5 = RotlXor(b5, ROTATION_2_2, b0 += b5);
+ b7 = RotlXor(b7, ROTATION_2_3, b2 += b7);
+
+ b1 = RotlXor(b1, ROTATION_3_0, b6 += b1);
+ b7 = RotlXor(b7, ROTATION_3_1, b0 += b7);
+ b5 = RotlXor(b5, ROTATION_3_2, b2 += b5);
+ b3 = RotlXor(b3, ROTATION_3_3, b4 += b3);
+
+ /*
+ * Subkey injection for first 4 rounds.
+ */
+ b0 += kw[dm9];
+ b1 += kw[dm9 + 1];
+ b2 += kw[dm9 + 2];
+ b3 += kw[dm9 + 3];
+ b4 += kw[dm9 + 4];
+ b5 += kw[dm9 + 5] + t[dm3];
+ b6 += kw[dm9 + 6] + t[dm3 + 1];
+ b7 += kw[dm9 + 7] + (uint)d;
+
+ /*
+ * 4 more rounds of mix/permute
+ */
+ b1 = RotlXor(b1, ROTATION_4_0, b0 += b1);
+ b3 = RotlXor(b3, ROTATION_4_1, b2 += b3);
+ b5 = RotlXor(b5, ROTATION_4_2, b4 += b5);
+ b7 = RotlXor(b7, ROTATION_4_3, b6 += b7);
+
+ b1 = RotlXor(b1, ROTATION_5_0, b2 += b1);
+ b7 = RotlXor(b7, ROTATION_5_1, b4 += b7);
+ b5 = RotlXor(b5, ROTATION_5_2, b6 += b5);
+ b3 = RotlXor(b3, ROTATION_5_3, b0 += b3);
+
+ b1 = RotlXor(b1, ROTATION_6_0, b4 += b1);
+ b3 = RotlXor(b3, ROTATION_6_1, b6 += b3);
+ b5 = RotlXor(b5, ROTATION_6_2, b0 += b5);
+ b7 = RotlXor(b7, ROTATION_6_3, b2 += b7);
+
+ b1 = RotlXor(b1, ROTATION_7_0, b6 += b1);
+ b7 = RotlXor(b7, ROTATION_7_1, b0 += b7);
+ b5 = RotlXor(b5, ROTATION_7_2, b2 += b5);
+ b3 = RotlXor(b3, ROTATION_7_3, b4 += b3);
+
+ /*
+ * Subkey injection for next 4 rounds.
+ */
+ b0 += kw[dm9 + 1];
+ b1 += kw[dm9 + 2];
+ b2 += kw[dm9 + 3];
+ b3 += kw[dm9 + 4];
+ b4 += kw[dm9 + 5];
+ b5 += kw[dm9 + 6] + t[dm3 + 1];
+ b6 += kw[dm9 + 7] + t[dm3 + 2];
+ b7 += kw[dm9 + 8] + (uint)d + 1;
+ }
+
+ /*
+ * Output cipher state.
+ */
+ outWords[0] = b0;
+ outWords[1] = b1;
+ outWords[2] = b2;
+ outWords[3] = b3;
+ outWords[4] = b4;
+ outWords[5] = b5;
+ outWords[6] = b6;
+ outWords[7] = b7;
+ }
+
+ internal override void DecryptBlock(ulong[] block, ulong[] state)
+ {
+ ulong[] kw = this.kw;
+ ulong[] t = this.t;
+ int[] mod9 = MOD9;
+ int[] mod3 = MOD3;
+
+ /* Help the JIT avoid index bounds checks */
+ if (kw.Length != 17)
+ {
+ throw new ArgumentException();
+ }
+ if (t.Length != 5)
+ {
+ throw new ArgumentException();
+ }
+
+ ulong b0 = block[0];
+ ulong b1 = block[1];
+ ulong b2 = block[2];
+ ulong b3 = block[3];
+ ulong b4 = block[4];
+ ulong b5 = block[5];
+ ulong b6 = block[6];
+ ulong b7 = block[7];
+
+ for (int d = (ROUNDS_512 / 4) - 1; d >= 1; d -= 2)
+ {
+ int dm9 = mod9[d];
+ int dm3 = mod3[d];
+
+ /* Reverse key injection for second 4 rounds */
+ b0 -= kw[dm9 + 1];
+ b1 -= kw[dm9 + 2];
+ b2 -= kw[dm9 + 3];
+ b3 -= kw[dm9 + 4];
+ b4 -= kw[dm9 + 5];
+ b5 -= kw[dm9 + 6] + t[dm3 + 1];
+ b6 -= kw[dm9 + 7] + t[dm3 + 2];
+ b7 -= kw[dm9 + 8] + (uint)d + 1;
+
+ /* Reverse second 4 mix/permute rounds */
+
+ b1 = XorRotr(b1, ROTATION_7_0, b6);
+ b6 -= b1;
+ b7 = XorRotr(b7, ROTATION_7_1, b0);
+ b0 -= b7;
+ b5 = XorRotr(b5, ROTATION_7_2, b2);
+ b2 -= b5;
+ b3 = XorRotr(b3, ROTATION_7_3, b4);
+ b4 -= b3;
+
+ b1 = XorRotr(b1, ROTATION_6_0, b4);
+ b4 -= b1;
+ b3 = XorRotr(b3, ROTATION_6_1, b6);
+ b6 -= b3;
+ b5 = XorRotr(b5, ROTATION_6_2, b0);
+ b0 -= b5;
+ b7 = XorRotr(b7, ROTATION_6_3, b2);
+ b2 -= b7;
+
+ b1 = XorRotr(b1, ROTATION_5_0, b2);
+ b2 -= b1;
+ b7 = XorRotr(b7, ROTATION_5_1, b4);
+ b4 -= b7;
+ b5 = XorRotr(b5, ROTATION_5_2, b6);
+ b6 -= b5;
+ b3 = XorRotr(b3, ROTATION_5_3, b0);
+ b0 -= b3;
+
+ b1 = XorRotr(b1, ROTATION_4_0, b0);
+ b0 -= b1;
+ b3 = XorRotr(b3, ROTATION_4_1, b2);
+ b2 -= b3;
+ b5 = XorRotr(b5, ROTATION_4_2, b4);
+ b4 -= b5;
+ b7 = XorRotr(b7, ROTATION_4_3, b6);
+ b6 -= b7;
+
+ /* Reverse key injection for first 4 rounds */
+ b0 -= kw[dm9];
+ b1 -= kw[dm9 + 1];
+ b2 -= kw[dm9 + 2];
+ b3 -= kw[dm9 + 3];
+ b4 -= kw[dm9 + 4];
+ b5 -= kw[dm9 + 5] + t[dm3];
+ b6 -= kw[dm9 + 6] + t[dm3 + 1];
+ b7 -= kw[dm9 + 7] + (uint)d;
+
+ /* Reverse first 4 mix/permute rounds */
+ b1 = XorRotr(b1, ROTATION_3_0, b6);
+ b6 -= b1;
+ b7 = XorRotr(b7, ROTATION_3_1, b0);
+ b0 -= b7;
+ b5 = XorRotr(b5, ROTATION_3_2, b2);
+ b2 -= b5;
+ b3 = XorRotr(b3, ROTATION_3_3, b4);
+ b4 -= b3;
+
+ b1 = XorRotr(b1, ROTATION_2_0, b4);
+ b4 -= b1;
+ b3 = XorRotr(b3, ROTATION_2_1, b6);
+ b6 -= b3;
+ b5 = XorRotr(b5, ROTATION_2_2, b0);
+ b0 -= b5;
+ b7 = XorRotr(b7, ROTATION_2_3, b2);
+ b2 -= b7;
+
+ b1 = XorRotr(b1, ROTATION_1_0, b2);
+ b2 -= b1;
+ b7 = XorRotr(b7, ROTATION_1_1, b4);
+ b4 -= b7;
+ b5 = XorRotr(b5, ROTATION_1_2, b6);
+ b6 -= b5;
+ b3 = XorRotr(b3, ROTATION_1_3, b0);
+ b0 -= b3;
+
+ b1 = XorRotr(b1, ROTATION_0_0, b0);
+ b0 -= b1;
+ b3 = XorRotr(b3, ROTATION_0_1, b2);
+ b2 -= b3;
+ b5 = XorRotr(b5, ROTATION_0_2, b4);
+ b4 -= b5;
+ b7 = XorRotr(b7, ROTATION_0_3, b6);
+ b6 -= b7;
+ }
+
+ /*
+ * First subkey uninjection.
+ */
+ b0 -= kw[0];
+ b1 -= kw[1];
+ b2 -= kw[2];
+ b3 -= kw[3];
+ b4 -= kw[4];
+ b5 -= kw[5] + t[0];
+ b6 -= kw[6] + t[1];
+ b7 -= kw[7];
+
+ /*
+ * Output cipher state.
+ */
+ state[0] = b0;
+ state[1] = b1;
+ state[2] = b2;
+ state[3] = b3;
+ state[4] = b4;
+ state[5] = b5;
+ state[6] = b6;
+ state[7] = b7;
+ }
+ }
+
+ private sealed class Threefish1024Cipher
+ : ThreefishCipher
+ {
+ /**
+ * Mix rotation constants defined in Skein 1.3 specification
+ */
+ private const int ROTATION_0_0 = 24, ROTATION_0_1 = 13, ROTATION_0_2 = 8, ROTATION_0_3 = 47;
+ private const int ROTATION_0_4 = 8, ROTATION_0_5 = 17, ROTATION_0_6 = 22, ROTATION_0_7 = 37;
+ private const int ROTATION_1_0 = 38, ROTATION_1_1 = 19, ROTATION_1_2 = 10, ROTATION_1_3 = 55;
+ private const int ROTATION_1_4 = 49, ROTATION_1_5 = 18, ROTATION_1_6 = 23, ROTATION_1_7 = 52;
+ private const int ROTATION_2_0 = 33, ROTATION_2_1 = 4, ROTATION_2_2 = 51, ROTATION_2_3 = 13;
+ private const int ROTATION_2_4 = 34, ROTATION_2_5 = 41, ROTATION_2_6 = 59, ROTATION_2_7 = 17;
+ private const int ROTATION_3_0 = 5, ROTATION_3_1 = 20, ROTATION_3_2 = 48, ROTATION_3_3 = 41;
+ private const int ROTATION_3_4 = 47, ROTATION_3_5 = 28, ROTATION_3_6 = 16, ROTATION_3_7 = 25;
+
+ private const int ROTATION_4_0 = 41, ROTATION_4_1 = 9, ROTATION_4_2 = 37, ROTATION_4_3 = 31;
+ private const int ROTATION_4_4 = 12, ROTATION_4_5 = 47, ROTATION_4_6 = 44, ROTATION_4_7 = 30;
+ private const int ROTATION_5_0 = 16, ROTATION_5_1 = 34, ROTATION_5_2 = 56, ROTATION_5_3 = 51;
+ private const int ROTATION_5_4 = 4, ROTATION_5_5 = 53, ROTATION_5_6 = 42, ROTATION_5_7 = 41;
+ private const int ROTATION_6_0 = 31, ROTATION_6_1 = 44, ROTATION_6_2 = 47, ROTATION_6_3 = 46;
+ private const int ROTATION_6_4 = 19, ROTATION_6_5 = 42, ROTATION_6_6 = 44, ROTATION_6_7 = 25;
+ private const int ROTATION_7_0 = 9, ROTATION_7_1 = 48, ROTATION_7_2 = 35, ROTATION_7_3 = 52;
+ private const int ROTATION_7_4 = 23, ROTATION_7_5 = 31, ROTATION_7_6 = 37, ROTATION_7_7 = 20;
+
+ public Threefish1024Cipher(ulong[] kw, ulong[] t)
+ : base(kw, t)
+ {
+ }
+
+ internal override void EncryptBlock(ulong[] block, ulong[] outWords)
+ {
+ ulong[] kw = this.kw;
+ ulong[] t = this.t;
+ int[] mod17 = MOD17;
+ int[] mod3 = MOD3;
+
+ /* Help the JIT avoid index bounds checks */
+ if (kw.Length != 33)
+ {
+ throw new ArgumentException();
+ }
+ if (t.Length != 5)
+ {
+ throw new ArgumentException();
+ }
+
+ /*
+ * Read 16 words of plaintext data, not using arrays for cipher state
+ */
+ ulong b0 = block[0];
+ ulong b1 = block[1];
+ ulong b2 = block[2];
+ ulong b3 = block[3];
+ ulong b4 = block[4];
+ ulong b5 = block[5];
+ ulong b6 = block[6];
+ ulong b7 = block[7];
+ ulong b8 = block[8];
+ ulong b9 = block[9];
+ ulong b10 = block[10];
+ ulong b11 = block[11];
+ ulong b12 = block[12];
+ ulong b13 = block[13];
+ ulong b14 = block[14];
+ ulong b15 = block[15];
+
+ /*
+ * First subkey injection.
+ */
+ b0 += kw[0];
+ b1 += kw[1];
+ b2 += kw[2];
+ b3 += kw[3];
+ b4 += kw[4];
+ b5 += kw[5];
+ b6 += kw[6];
+ b7 += kw[7];
+ b8 += kw[8];
+ b9 += kw[9];
+ b10 += kw[10];
+ b11 += kw[11];
+ b12 += kw[12];
+ b13 += kw[13] + t[0];
+ b14 += kw[14] + t[1];
+ b15 += kw[15];
+
+ /*
+ * Rounds loop, unrolled to 8 rounds per iteration.
+ *
+ * Unrolling to multiples of 4 avoids the mod 4 check for key injection, and allows
+ * inlining of the permutations, which cycle every of 4 rounds (avoiding array
+ * index/lookup).
+ *
+ * Unrolling to multiples of 8 avoids the mod 8 rotation constant lookup, and allows
+ * inlining constant rotation values (avoiding array index/lookup).
+ */
+
+ for (int d = 1; d < (ROUNDS_1024 / 4); d += 2)
+ {
+ int dm17 = mod17[d];
+ int dm3 = mod3[d];
+
+ /*
+ * 4 rounds of mix and permute.
+ *
+ * Permute schedule has a 4 round cycle, so permutes are inlined in the mix
+ * operations in each 4 round block.
+ */
+ b1 = RotlXor(b1, ROTATION_0_0, b0 += b1);
+ b3 = RotlXor(b3, ROTATION_0_1, b2 += b3);
+ b5 = RotlXor(b5, ROTATION_0_2, b4 += b5);
+ b7 = RotlXor(b7, ROTATION_0_3, b6 += b7);
+ b9 = RotlXor(b9, ROTATION_0_4, b8 += b9);
+ b11 = RotlXor(b11, ROTATION_0_5, b10 += b11);
+ b13 = RotlXor(b13, ROTATION_0_6, b12 += b13);
+ b15 = RotlXor(b15, ROTATION_0_7, b14 += b15);
+
+ b9 = RotlXor(b9, ROTATION_1_0, b0 += b9);
+ b13 = RotlXor(b13, ROTATION_1_1, b2 += b13);
+ b11 = RotlXor(b11, ROTATION_1_2, b6 += b11);
+ b15 = RotlXor(b15, ROTATION_1_3, b4 += b15);
+ b7 = RotlXor(b7, ROTATION_1_4, b10 += b7);
+ b3 = RotlXor(b3, ROTATION_1_5, b12 += b3);
+ b5 = RotlXor(b5, ROTATION_1_6, b14 += b5);
+ b1 = RotlXor(b1, ROTATION_1_7, b8 += b1);
+
+ b7 = RotlXor(b7, ROTATION_2_0, b0 += b7);
+ b5 = RotlXor(b5, ROTATION_2_1, b2 += b5);
+ b3 = RotlXor(b3, ROTATION_2_2, b4 += b3);
+ b1 = RotlXor(b1, ROTATION_2_3, b6 += b1);
+ b15 = RotlXor(b15, ROTATION_2_4, b12 += b15);
+ b13 = RotlXor(b13, ROTATION_2_5, b14 += b13);
+ b11 = RotlXor(b11, ROTATION_2_6, b8 += b11);
+ b9 = RotlXor(b9, ROTATION_2_7, b10 += b9);
+
+ b15 = RotlXor(b15, ROTATION_3_0, b0 += b15);
+ b11 = RotlXor(b11, ROTATION_3_1, b2 += b11);
+ b13 = RotlXor(b13, ROTATION_3_2, b6 += b13);
+ b9 = RotlXor(b9, ROTATION_3_3, b4 += b9);
+ b1 = RotlXor(b1, ROTATION_3_4, b14 += b1);
+ b5 = RotlXor(b5, ROTATION_3_5, b8 += b5);
+ b3 = RotlXor(b3, ROTATION_3_6, b10 += b3);
+ b7 = RotlXor(b7, ROTATION_3_7, b12 += b7);
+
+ /*
+ * Subkey injection for first 4 rounds.
+ */
+ b0 += kw[dm17];
+ b1 += kw[dm17 + 1];
+ b2 += kw[dm17 + 2];
+ b3 += kw[dm17 + 3];
+ b4 += kw[dm17 + 4];
+ b5 += kw[dm17 + 5];
+ b6 += kw[dm17 + 6];
+ b7 += kw[dm17 + 7];
+ b8 += kw[dm17 + 8];
+ b9 += kw[dm17 + 9];
+ b10 += kw[dm17 + 10];
+ b11 += kw[dm17 + 11];
+ b12 += kw[dm17 + 12];
+ b13 += kw[dm17 + 13] + t[dm3];
+ b14 += kw[dm17 + 14] + t[dm3 + 1];
+ b15 += kw[dm17 + 15] + (uint)d;
+
+ /*
+ * 4 more rounds of mix/permute
+ */
+ b1 = RotlXor(b1, ROTATION_4_0, b0 += b1);
+ b3 = RotlXor(b3, ROTATION_4_1, b2 += b3);
+ b5 = RotlXor(b5, ROTATION_4_2, b4 += b5);
+ b7 = RotlXor(b7, ROTATION_4_3, b6 += b7);
+ b9 = RotlXor(b9, ROTATION_4_4, b8 += b9);
+ b11 = RotlXor(b11, ROTATION_4_5, b10 += b11);
+ b13 = RotlXor(b13, ROTATION_4_6, b12 += b13);
+ b15 = RotlXor(b15, ROTATION_4_7, b14 += b15);
+
+ b9 = RotlXor(b9, ROTATION_5_0, b0 += b9);
+ b13 = RotlXor(b13, ROTATION_5_1, b2 += b13);
+ b11 = RotlXor(b11, ROTATION_5_2, b6 += b11);
+ b15 = RotlXor(b15, ROTATION_5_3, b4 += b15);
+ b7 = RotlXor(b7, ROTATION_5_4, b10 += b7);
+ b3 = RotlXor(b3, ROTATION_5_5, b12 += b3);
+ b5 = RotlXor(b5, ROTATION_5_6, b14 += b5);
+ b1 = RotlXor(b1, ROTATION_5_7, b8 += b1);
+
+ b7 = RotlXor(b7, ROTATION_6_0, b0 += b7);
+ b5 = RotlXor(b5, ROTATION_6_1, b2 += b5);
+ b3 = RotlXor(b3, ROTATION_6_2, b4 += b3);
+ b1 = RotlXor(b1, ROTATION_6_3, b6 += b1);
+ b15 = RotlXor(b15, ROTATION_6_4, b12 += b15);
+ b13 = RotlXor(b13, ROTATION_6_5, b14 += b13);
+ b11 = RotlXor(b11, ROTATION_6_6, b8 += b11);
+ b9 = RotlXor(b9, ROTATION_6_7, b10 += b9);
+
+ b15 = RotlXor(b15, ROTATION_7_0, b0 += b15);
+ b11 = RotlXor(b11, ROTATION_7_1, b2 += b11);
+ b13 = RotlXor(b13, ROTATION_7_2, b6 += b13);
+ b9 = RotlXor(b9, ROTATION_7_3, b4 += b9);
+ b1 = RotlXor(b1, ROTATION_7_4, b14 += b1);
+ b5 = RotlXor(b5, ROTATION_7_5, b8 += b5);
+ b3 = RotlXor(b3, ROTATION_7_6, b10 += b3);
+ b7 = RotlXor(b7, ROTATION_7_7, b12 += b7);
+
+ /*
+ * Subkey injection for next 4 rounds.
+ */
+ b0 += kw[dm17 + 1];
+ b1 += kw[dm17 + 2];
+ b2 += kw[dm17 + 3];
+ b3 += kw[dm17 + 4];
+ b4 += kw[dm17 + 5];
+ b5 += kw[dm17 + 6];
+ b6 += kw[dm17 + 7];
+ b7 += kw[dm17 + 8];
+ b8 += kw[dm17 + 9];
+ b9 += kw[dm17 + 10];
+ b10 += kw[dm17 + 11];
+ b11 += kw[dm17 + 12];
+ b12 += kw[dm17 + 13];
+ b13 += kw[dm17 + 14] + t[dm3 + 1];
+ b14 += kw[dm17 + 15] + t[dm3 + 2];
+ b15 += kw[dm17 + 16] + (uint)d + 1;
+
+ }
+
+ /*
+ * Output cipher state.
+ */
+ outWords[0] = b0;
+ outWords[1] = b1;
+ outWords[2] = b2;
+ outWords[3] = b3;
+ outWords[4] = b4;
+ outWords[5] = b5;
+ outWords[6] = b6;
+ outWords[7] = b7;
+ outWords[8] = b8;
+ outWords[9] = b9;
+ outWords[10] = b10;
+ outWords[11] = b11;
+ outWords[12] = b12;
+ outWords[13] = b13;
+ outWords[14] = b14;
+ outWords[15] = b15;
+ }
+
+ internal override void DecryptBlock(ulong[] block, ulong[] state)
+ {
+ ulong[] kw = this.kw;
+ ulong[] t = this.t;
+ int[] mod17 = MOD17;
+ int[] mod3 = MOD3;
+
+ /* Help the JIT avoid index bounds checks */
+ if (kw.Length != 33)
+ {
+ throw new ArgumentException();
+ }
+ if (t.Length != 5)
+ {
+ throw new ArgumentException();
+ }
+
+ ulong b0 = block[0];
+ ulong b1 = block[1];
+ ulong b2 = block[2];
+ ulong b3 = block[3];
+ ulong b4 = block[4];
+ ulong b5 = block[5];
+ ulong b6 = block[6];
+ ulong b7 = block[7];
+ ulong b8 = block[8];
+ ulong b9 = block[9];
+ ulong b10 = block[10];
+ ulong b11 = block[11];
+ ulong b12 = block[12];
+ ulong b13 = block[13];
+ ulong b14 = block[14];
+ ulong b15 = block[15];
+
+ for (int d = (ROUNDS_1024 / 4) - 1; d >= 1; d -= 2)
+ {
+ int dm17 = mod17[d];
+ int dm3 = mod3[d];
+
+ /* Reverse key injection for second 4 rounds */
+ b0 -= kw[dm17 + 1];
+ b1 -= kw[dm17 + 2];
+ b2 -= kw[dm17 + 3];
+ b3 -= kw[dm17 + 4];
+ b4 -= kw[dm17 + 5];
+ b5 -= kw[dm17 + 6];
+ b6 -= kw[dm17 + 7];
+ b7 -= kw[dm17 + 8];
+ b8 -= kw[dm17 + 9];
+ b9 -= kw[dm17 + 10];
+ b10 -= kw[dm17 + 11];
+ b11 -= kw[dm17 + 12];
+ b12 -= kw[dm17 + 13];
+ b13 -= kw[dm17 + 14] + t[dm3 + 1];
+ b14 -= kw[dm17 + 15] + t[dm3 + 2];
+ b15 -= kw[dm17 + 16] + (uint)d + 1;
+
+ /* Reverse second 4 mix/permute rounds */
+ b15 = XorRotr(b15, ROTATION_7_0, b0);
+ b0 -= b15;
+ b11 = XorRotr(b11, ROTATION_7_1, b2);
+ b2 -= b11;
+ b13 = XorRotr(b13, ROTATION_7_2, b6);
+ b6 -= b13;
+ b9 = XorRotr(b9, ROTATION_7_3, b4);
+ b4 -= b9;
+ b1 = XorRotr(b1, ROTATION_7_4, b14);
+ b14 -= b1;
+ b5 = XorRotr(b5, ROTATION_7_5, b8);
+ b8 -= b5;
+ b3 = XorRotr(b3, ROTATION_7_6, b10);
+ b10 -= b3;
+ b7 = XorRotr(b7, ROTATION_7_7, b12);
+ b12 -= b7;
+
+ b7 = XorRotr(b7, ROTATION_6_0, b0);
+ b0 -= b7;
+ b5 = XorRotr(b5, ROTATION_6_1, b2);
+ b2 -= b5;
+ b3 = XorRotr(b3, ROTATION_6_2, b4);
+ b4 -= b3;
+ b1 = XorRotr(b1, ROTATION_6_3, b6);
+ b6 -= b1;
+ b15 = XorRotr(b15, ROTATION_6_4, b12);
+ b12 -= b15;
+ b13 = XorRotr(b13, ROTATION_6_5, b14);
+ b14 -= b13;
+ b11 = XorRotr(b11, ROTATION_6_6, b8);
+ b8 -= b11;
+ b9 = XorRotr(b9, ROTATION_6_7, b10);
+ b10 -= b9;
+
+ b9 = XorRotr(b9, ROTATION_5_0, b0);
+ b0 -= b9;
+ b13 = XorRotr(b13, ROTATION_5_1, b2);
+ b2 -= b13;
+ b11 = XorRotr(b11, ROTATION_5_2, b6);
+ b6 -= b11;
+ b15 = XorRotr(b15, ROTATION_5_3, b4);
+ b4 -= b15;
+ b7 = XorRotr(b7, ROTATION_5_4, b10);
+ b10 -= b7;
+ b3 = XorRotr(b3, ROTATION_5_5, b12);
+ b12 -= b3;
+ b5 = XorRotr(b5, ROTATION_5_6, b14);
+ b14 -= b5;
+ b1 = XorRotr(b1, ROTATION_5_7, b8);
+ b8 -= b1;
+
+ b1 = XorRotr(b1, ROTATION_4_0, b0);
+ b0 -= b1;
+ b3 = XorRotr(b3, ROTATION_4_1, b2);
+ b2 -= b3;
+ b5 = XorRotr(b5, ROTATION_4_2, b4);
+ b4 -= b5;
+ b7 = XorRotr(b7, ROTATION_4_3, b6);
+ b6 -= b7;
+ b9 = XorRotr(b9, ROTATION_4_4, b8);
+ b8 -= b9;
+ b11 = XorRotr(b11, ROTATION_4_5, b10);
+ b10 -= b11;
+ b13 = XorRotr(b13, ROTATION_4_6, b12);
+ b12 -= b13;
+ b15 = XorRotr(b15, ROTATION_4_7, b14);
+ b14 -= b15;
+
+ /* Reverse key injection for first 4 rounds */
+ b0 -= kw[dm17];
+ b1 -= kw[dm17 + 1];
+ b2 -= kw[dm17 + 2];
+ b3 -= kw[dm17 + 3];
+ b4 -= kw[dm17 + 4];
+ b5 -= kw[dm17 + 5];
+ b6 -= kw[dm17 + 6];
+ b7 -= kw[dm17 + 7];
+ b8 -= kw[dm17 + 8];
+ b9 -= kw[dm17 + 9];
+ b10 -= kw[dm17 + 10];
+ b11 -= kw[dm17 + 11];
+ b12 -= kw[dm17 + 12];
+ b13 -= kw[dm17 + 13] + t[dm3];
+ b14 -= kw[dm17 + 14] + t[dm3 + 1];
+ b15 -= kw[dm17 + 15] + (uint)d;
+
+ /* Reverse first 4 mix/permute rounds */
+ b15 = XorRotr(b15, ROTATION_3_0, b0);
+ b0 -= b15;
+ b11 = XorRotr(b11, ROTATION_3_1, b2);
+ b2 -= b11;
+ b13 = XorRotr(b13, ROTATION_3_2, b6);
+ b6 -= b13;
+ b9 = XorRotr(b9, ROTATION_3_3, b4);
+ b4 -= b9;
+ b1 = XorRotr(b1, ROTATION_3_4, b14);
+ b14 -= b1;
+ b5 = XorRotr(b5, ROTATION_3_5, b8);
+ b8 -= b5;
+ b3 = XorRotr(b3, ROTATION_3_6, b10);
+ b10 -= b3;
+ b7 = XorRotr(b7, ROTATION_3_7, b12);
+ b12 -= b7;
+
+ b7 = XorRotr(b7, ROTATION_2_0, b0);
+ b0 -= b7;
+ b5 = XorRotr(b5, ROTATION_2_1, b2);
+ b2 -= b5;
+ b3 = XorRotr(b3, ROTATION_2_2, b4);
+ b4 -= b3;
+ b1 = XorRotr(b1, ROTATION_2_3, b6);
+ b6 -= b1;
+ b15 = XorRotr(b15, ROTATION_2_4, b12);
+ b12 -= b15;
+ b13 = XorRotr(b13, ROTATION_2_5, b14);
+ b14 -= b13;
+ b11 = XorRotr(b11, ROTATION_2_6, b8);
+ b8 -= b11;
+ b9 = XorRotr(b9, ROTATION_2_7, b10);
+ b10 -= b9;
+
+ b9 = XorRotr(b9, ROTATION_1_0, b0);
+ b0 -= b9;
+ b13 = XorRotr(b13, ROTATION_1_1, b2);
+ b2 -= b13;
+ b11 = XorRotr(b11, ROTATION_1_2, b6);
+ b6 -= b11;
+ b15 = XorRotr(b15, ROTATION_1_3, b4);
+ b4 -= b15;
+ b7 = XorRotr(b7, ROTATION_1_4, b10);
+ b10 -= b7;
+ b3 = XorRotr(b3, ROTATION_1_5, b12);
+ b12 -= b3;
+ b5 = XorRotr(b5, ROTATION_1_6, b14);
+ b14 -= b5;
+ b1 = XorRotr(b1, ROTATION_1_7, b8);
+ b8 -= b1;
+
+ b1 = XorRotr(b1, ROTATION_0_0, b0);
+ b0 -= b1;
+ b3 = XorRotr(b3, ROTATION_0_1, b2);
+ b2 -= b3;
+ b5 = XorRotr(b5, ROTATION_0_2, b4);
+ b4 -= b5;
+ b7 = XorRotr(b7, ROTATION_0_3, b6);
+ b6 -= b7;
+ b9 = XorRotr(b9, ROTATION_0_4, b8);
+ b8 -= b9;
+ b11 = XorRotr(b11, ROTATION_0_5, b10);
+ b10 -= b11;
+ b13 = XorRotr(b13, ROTATION_0_6, b12);
+ b12 -= b13;
+ b15 = XorRotr(b15, ROTATION_0_7, b14);
+ b14 -= b15;
+ }
+
+ /*
+ * First subkey uninjection.
+ */
+ b0 -= kw[0];
+ b1 -= kw[1];
+ b2 -= kw[2];
+ b3 -= kw[3];
+ b4 -= kw[4];
+ b5 -= kw[5];
+ b6 -= kw[6];
+ b7 -= kw[7];
+ b8 -= kw[8];
+ b9 -= kw[9];
+ b10 -= kw[10];
+ b11 -= kw[11];
+ b12 -= kw[12];
+ b13 -= kw[13] + t[0];
+ b14 -= kw[14] + t[1];
+ b15 -= kw[15];
+
+ /*
+ * Output cipher state.
+ */
+ state[0] = b0;
+ state[1] = b1;
+ state[2] = b2;
+ state[3] = b3;
+ state[4] = b4;
+ state[5] = b5;
+ state[6] = b6;
+ state[7] = b7;
+ state[8] = b8;
+ state[9] = b9;
+ state[10] = b10;
+ state[11] = b11;
+ state[12] = b12;
+ state[13] = b13;
+ state[14] = b14;
+ state[15] = b15;
+ }
+
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/crypto/src/crypto/macs/HMac.cs b/crypto/src/crypto/macs/HMac.cs
index 7ae1e02b9..460f3c5a0 100644
--- a/crypto/src/crypto/macs/HMac.cs
+++ b/crypto/src/crypto/macs/HMac.cs
@@ -3,6 +3,7 @@ using System.Collections;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Macs
{
@@ -20,6 +21,8 @@ namespace Org.BouncyCastle.Crypto.Macs
private readonly IDigest digest;
private readonly int digestSize;
private readonly int blockLength;
+ private IMemoable ipadState;
+ private IMemoable opadState;
private readonly byte[] inputPad;
private readonly byte[] outputBuf;
@@ -68,8 +71,19 @@ namespace Org.BouncyCastle.Crypto.Macs
XorPad(inputPad, blockLength, IPAD);
XorPad(outputBuf, blockLength, OPAD);
- // Initialise the digest
+ if (digest is IMemoable)
+ {
+ opadState = ((IMemoable)digest).Copy();
+
+ ((IDigest)opadState).BlockUpdate(outputBuf, 0, blockLength);
+ }
+
digest.BlockUpdate(inputPad, 0, inputPad.Length);
+
+ if (digest is IMemoable)
+ {
+ ipadState = ((IMemoable)digest).Copy();
+ }
}
public virtual int GetMacSize()
@@ -90,13 +104,29 @@ namespace Org.BouncyCastle.Crypto.Macs
public virtual int DoFinal(byte[] output, int outOff)
{
digest.DoFinal(outputBuf, blockLength);
- digest.BlockUpdate(outputBuf, 0, outputBuf.Length);
- int len = digest.DoFinal(output, outOff);
- Array.Clear(outputBuf, blockLength, digestSize);
-
- // Initialise the digest
- digest.BlockUpdate(inputPad, 0, inputPad.Length);
+ if (opadState != null)
+ {
+ ((IMemoable)digest).Reset(opadState);
+ digest.BlockUpdate(outputBuf, blockLength, digest.GetDigestSize());
+ }
+ else
+ {
+ digest.BlockUpdate(outputBuf, 0, outputBuf.Length);
+ }
+
+ int len = digest.DoFinal(output, outOff);
+
+ Array.Clear(outputBuf, blockLength, digestSize);
+
+ if (ipadState != null)
+ {
+ ((IMemoable)digest).Reset(ipadState);
+ }
+ else
+ {
+ digest.BlockUpdate(inputPad, 0, inputPad.Length);
+ }
return len;
}
diff --git a/crypto/src/crypto/macs/SkeinMac.cs b/crypto/src/crypto/macs/SkeinMac.cs
new file mode 100644
index 000000000..1d61a41ca
--- /dev/null
+++ b/crypto/src/crypto/macs/SkeinMac.cs
@@ -0,0 +1,117 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Macs
+{
+
+ /// <summary>
+ /// Implementation of the Skein parameterised MAC function in 256, 512 and 1024 bit block sizes,
+ /// based on the <see cref="Org.BouncyCastle.Crypto.Engines.ThreefishEngine">Threefish</see> tweakable block cipher.
+ /// </summary>
+ /// <remarks>
+ /// This is the 1.3 version of Skein defined in the Skein hash function submission to the NIST SHA-3
+ /// competition in October 2010.
+ /// <p/>
+ /// Skein was designed by Niels Ferguson - Stefan Lucks - Bruce Schneier - Doug Whiting - Mihir
+ /// Bellare - Tadayoshi Kohno - Jon Callas - Jesse Walker.
+ /// </remarks>
+ /// <seealso cref="Org.BouncyCastle.Crypto.Digests.SkeinEngine"/>
+ /// <seealso cref="Org.BouncyCastle.Crypto.Parameters.SkeinParameters"/>
+ public class SkeinMac
+ : IMac
+ {
+ /// <summary>
+ /// 256 bit block size - Skein-256
+ /// </summary>
+ public const int SKEIN_256 = SkeinEngine.SKEIN_256;
+ /// <summary>
+ /// 512 bit block size - Skein-512
+ /// </summary>
+ public const int SKEIN_512 = SkeinEngine.SKEIN_512;
+ /// <summary>
+ /// 1024 bit block size - Skein-1024
+ /// </summary>
+ public const int SKEIN_1024 = SkeinEngine.SKEIN_1024;
+
+ private readonly SkeinEngine engine;
+
+ /// <summary>
+ /// Constructs a Skein MAC with an internal state size and output size.
+ /// </summary>
+ /// <param name="stateSizeBits">the internal state size in bits - one of <see cref="SKEIN_256"/> <see cref="SKEIN_512"/> or
+ /// <see cref="SKEIN_1024"/>.</param>
+ /// <param name="digestSizeBits">the output/MAC size to produce in bits, which must be an integral number of
+ /// bytes.</param>
+ public SkeinMac(int stateSizeBits, int digestSizeBits)
+ {
+ this.engine = new SkeinEngine(stateSizeBits, digestSizeBits);
+ }
+
+ public SkeinMac(SkeinMac mac)
+ {
+ this.engine = new SkeinEngine(mac.engine);
+ }
+
+ public string AlgorithmName
+ {
+ get { return "Skein-MAC-" + (engine.BlockSize * 8) + "-" + (engine.OutputSize * 8); }
+ }
+
+ /// <summary>
+ /// Optionally initialises the Skein digest with the provided parameters.
+ /// </summary>
+ /// See <see cref="Org.BouncyCastle.Crypto.Parameters.SkeinParameters"></see> for details on the parameterisation of the Skein hash function.
+ /// <param name="parameters">the parameters to apply to this engine, or <code>null</code> to use no parameters.</param>
+ public void Init(ICipherParameters parameters)
+ {
+ SkeinParameters skeinParameters;
+ if (parameters is SkeinParameters)
+ {
+ skeinParameters = (SkeinParameters)parameters;
+ }
+ else if (parameters is KeyParameter)
+ {
+ skeinParameters = new SkeinParameters.Builder().SetKey(((KeyParameter)parameters).GetKey()).Build();
+ }
+ else
+ {
+ throw new ArgumentException("Invalid parameter passed to Skein MAC init - "
+ + parameters.GetType().Name);
+ }
+ if (skeinParameters.GetKey() == null)
+ {
+ throw new ArgumentException("Skein MAC requires a key parameter.");
+ }
+ engine.Init(skeinParameters);
+ }
+
+ public int GetMacSize()
+ {
+ return engine.OutputSize;
+ }
+
+ public void Reset()
+ {
+ engine.Reset();
+ }
+
+ public void Update(byte inByte)
+ {
+ engine.Update(inByte);
+ }
+
+ public void BlockUpdate(byte[] input, int inOff, int len)
+ {
+ engine.Update(input, inOff, len);
+ }
+
+ public int DoFinal(byte[] output, int outOff)
+ {
+ return engine.DoFinal(output, outOff);
+ }
+
+ }
+}
diff --git a/crypto/src/crypto/parameters/SkeinParameters.cs b/crypto/src/crypto/parameters/SkeinParameters.cs
new file mode 100644
index 000000000..bbd25e0e0
--- /dev/null
+++ b/crypto/src/crypto/parameters/SkeinParameters.cs
@@ -0,0 +1,285 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+
+ /// <summary>
+ /// Parameters for the Skein hash function - a series of byte[] strings identified by integer tags.
+ /// </summary>
+ /// <remarks>
+ /// Parameterised Skein can be used for:
+ /// <ul>
+ /// <li>MAC generation, by providing a <see cref="SkeinParameters.Builder.SetKey(byte[])">key</see>.</li>
+ /// <li>Randomised hashing, by providing a <see cref="SkeinParameters.Builder.SetNoce(byte[])">nonce</see>.</li>
+ /// <li>A hash function for digital signatures, associating a
+ /// <see cref="SkeinParameters.Builder.SetPublicKey(byte[])">public key</see> with the message digest.</li>
+ /// <li>A key derivation function, by providing a
+ /// <see cref="SkeinParameters.Builder.SetKeyIdentifier(byte[])">key identifier</see>.</li>
+ /// <li>Personalised hashing, by providing a
+ /// <see cref="SkeinParameters.Builder.SetPersonalisation(DateTime,string,string)">recommended format</see> or
+ /// <see cref="SkeinParameters.Builder.SetPersonalisation(byte[])">arbitrary</see> personalisation string.</li>
+ /// </ul>
+ /// </remarks>
+ /// <seealso cref="Org.BouncyCastle.Crypto.Digests.SkeinEngine"/>
+ /// <seealso cref="Org.BouncyCastle.Crypto.Digests.SkeinDigest"/>
+ /// <seealso cref="Org.BouncyCastle.Crypto.Macs.SkeinMac"/>
+ public class SkeinParameters
+ : ICipherParameters
+ {
+ /// <summary>
+ /// The parameter type for a secret key, supporting MAC or KDF functions: 0
+ /// </summary>
+ public const int PARAM_TYPE_KEY = 0;
+
+ /// <summary>
+ /// The parameter type for the Skein configuration block: 4
+ /// </summary>
+ public const int PARAM_TYPE_CONFIG = 4;
+
+ /// <summary>
+ /// The parameter type for a personalisation string: 8
+ /// </summary>
+ public const int PARAM_TYPE_PERSONALISATION = 8;
+
+ /// <summary>
+ /// The parameter type for a public key: 12
+ /// </summary>
+ public const int PARAM_TYPE_PUBLIC_KEY = 12;
+
+ /// <summary>
+ /// The parameter type for a key identifier string: 16
+ /// </summary>
+ public const int PARAM_TYPE_KEY_IDENTIFIER = 16;
+
+ /// <summary>
+ /// The parameter type for a nonce: 20
+ /// </summary>
+ public const int PARAM_TYPE_NONCE = 20;
+
+ /// <summary>
+ /// The parameter type for the message: 48
+ /// </summary>
+ public const int PARAM_TYPE_MESSAGE = 48;
+
+ /// <summary>
+ /// The parameter type for the output transformation: 63
+ /// </summary>
+ public const int PARAM_TYPE_OUTPUT = 63;
+
+ private IDictionary parameters;
+
+ public SkeinParameters()
+ : this(Platform.CreateHashtable())
+
+ {
+ }
+
+ private SkeinParameters(IDictionary parameters)
+ {
+ this.parameters = parameters;
+ }
+
+ /// <summary>
+ /// Obtains a map of type (int) to value (byte[]) for the parameters tracked in this object.
+ /// </summary>
+ public IDictionary GetParameters()
+ {
+ return parameters;
+ }
+
+ /// <summary>
+ /// Obtains the value of the <see cref="PARAM_TYPE_KEY">key parameter</see>, or <code>null</code> if not
+ /// set.
+ /// </summary>
+ /// <returns>The key.</returns>
+ public byte[] GetKey()
+ {
+ return (byte[])parameters[PARAM_TYPE_KEY];
+ }
+
+ /// <summary>
+ /// Obtains the value of the <see cref="PARAM_TYPE_PERSONALISATION">personalisation parameter</see>, or
+ /// <code>null</code> if not set.
+ /// </summary>
+ public byte[] GetPersonalisation()
+ {
+ return (byte[])parameters[PARAM_TYPE_PERSONALISATION];
+ }
+
+ /// <summary>
+ /// Obtains the value of the <see cref="PARAM_TYPE_PUBLIC_KEY">public key parameter</see>, or
+ /// <code>null</code> if not set.
+ /// </summary>
+ public byte[] GetPublicKey()
+ {
+ return (byte[])parameters[PARAM_TYPE_PUBLIC_KEY];
+ }
+
+ /// <summary>
+ /// Obtains the value of the <see cref="PARAM_TYPE_KEY_IDENTIFIER key identifier parameter</see>, or
+ /// <code>null</code> if not set.
+ /// </summary>
+ public byte[] GetKeyIdentifier()
+ {
+ return (byte[])parameters[PARAM_TYPE_KEY_IDENTIFIER];
+ }
+
+ /// <summary>
+ /// Obtains the value of the <see cref="PARAM_TYPE_NONCE nonce parameter</see>, or <code>null</code> if
+ /// not set.
+ /// </summary>
+ public byte[] GetNonce()
+ {
+ return (byte[])parameters[PARAM_TYPE_NONCE];
+ }
+
+ /// <summary>
+ /// A builder for <see cref="SkeinParameters"/>.
+ /// </summary>
+ public class Builder
+ {
+ private IDictionary parameters = Platform.CreateHashtable();
+
+ public Builder()
+ {
+ }
+
+ public Builder(IDictionary paramsMap)
+ {
+ IEnumerator keys = paramsMap.Keys.GetEnumerator();
+ while (keys.MoveNext())
+ {
+ int key = (int)keys.Current;
+ parameters.Add(key, paramsMap[key]);
+ }
+ }
+
+ public Builder(SkeinParameters parameters)
+ {
+ IEnumerator keys = parameters.parameters.Keys.GetEnumerator();
+ while (keys.MoveNext())
+ {
+ int key = (int)keys.Current;
+ this.parameters.Add(key, parameters.parameters[key]);
+ }
+ }
+
+ /// <summary>
+ /// Sets a parameters to apply to the Skein hash function.
+ /// </summary>
+ /// <remarks>
+ /// Parameter types must be in the range 0,5..62, and cannot use the value 48
+ /// (reserved for message body).
+ /// <p/>
+ /// Parameters with type < 48 are processed before
+ /// the message content, parameters with type > 48
+ /// are processed after the message and prior to output.
+ /// </remarks>
+ /// <param name="type">the type of the parameter, in the range 5..62.</param>
+ /// <param name="value">the byte sequence of the parameter.</param>
+ public Builder Set(int type, byte[] value)
+ {
+ if (value == null)
+ {
+ throw new ArgumentException("Parameter value must not be null.");
+ }
+ if ((type != PARAM_TYPE_KEY)
+ && (type <= PARAM_TYPE_CONFIG || type >= PARAM_TYPE_OUTPUT || type == PARAM_TYPE_MESSAGE))
+ {
+ throw new ArgumentException("Parameter types must be in the range 0,5..47,49..62.");
+ }
+ if (type == PARAM_TYPE_CONFIG)
+ {
+ throw new ArgumentException("Parameter type " + PARAM_TYPE_CONFIG
+ + " is reserved for internal use.");
+ }
+ this.parameters.Add(type, value);
+ return this;
+ }
+
+ /// <summary>
+ /// Sets the <see cref="SkeinParameters.PARAM_TYPE_KEY"/> parameter.
+ /// </summary>
+ public Builder SetKey(byte[] key)
+ {
+ return Set(PARAM_TYPE_KEY, key);
+ }
+
+ /// <summary>
+ /// Sets the <see cref="SkeinParameters.PARAM_TYPE_PERSONALISATION"/> parameter.
+ /// </summary>
+ public Builder SetPersonalisation(byte[] personalisation)
+ {
+ return Set(PARAM_TYPE_PERSONALISATION, personalisation);
+ }
+
+ /// <summary>
+ /// Implements the recommended personalisation format for Skein defined in Section 4.11 of
+ /// the Skein 1.3 specification.
+ /// </summary>
+ /// <remarks>
+ /// The format is <code>YYYYMMDD email@address distinguisher</code>, encoded to a byte
+ /// sequence using UTF-8 encoding.
+ /// </remarks>
+ /// <param name="date">the date the personalised application of the Skein was defined.</param>
+ /// <param name="emailAddress">the email address of the creation of the personalised application.</param>
+ /// <param name="distinguisher">an arbitrary personalisation string distinguishing the application.</param>
+ public Builder SetPersonalisation(DateTime date, string emailAddress, string distinguisher)
+ {
+ try
+ {
+ MemoryStream bout = new MemoryStream();
+ StreamWriter outBytes = new StreamWriter(bout, System.Text.Encoding.UTF8);
+ outBytes.Write(date.ToString("YYYYMMDD"));
+ outBytes.Write(" ");
+ outBytes.Write(emailAddress);
+ outBytes.Write(" ");
+ outBytes.Write(distinguisher);
+ outBytes.Close();
+ return Set(PARAM_TYPE_PERSONALISATION, bout.ToArray());
+ }
+ catch (IOException e)
+ {
+ throw new InvalidOperationException("Byte I/O failed.", e);
+ }
+ }
+
+ /// <summary>
+ /// Sets the <see cref="SkeinParameters.PARAM_TYPE_KEY_IDENTIFIER"/> parameter.
+ /// </summary>
+ public Builder SetPublicKey(byte[] publicKey)
+ {
+ return Set(PARAM_TYPE_PUBLIC_KEY, publicKey);
+ }
+
+ /// <summary>
+ /// Sets the <see cref="SkeinParameters.PARAM_TYPE_KEY_IDENTIFIER"/> parameter.
+ /// </summary>
+ public Builder SetKeyIdentifier(byte[] keyIdentifier)
+ {
+ return Set(PARAM_TYPE_KEY_IDENTIFIER, keyIdentifier);
+ }
+
+ /// <summary>
+ /// Sets the <see cref="SkeinParameters.PARAM_TYPE_NONCE"/> parameter.
+ /// </summary>
+ public Builder SetNonce(byte[] nonce)
+ {
+ return Set(PARAM_TYPE_NONCE, nonce);
+ }
+
+ /// <summary>
+ /// Constructs a new <see cref="SkeinParameters"/> instance with the parameters provided to this
+ /// builder.
+ /// </summary>
+ public SkeinParameters Build()
+ {
+ return new SkeinParameters(parameters);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/crypto/src/crypto/parameters/TweakableBlockCipherParameters.cs b/crypto/src/crypto/parameters/TweakableBlockCipherParameters.cs
new file mode 100644
index 000000000..f75726600
--- /dev/null
+++ b/crypto/src/crypto/parameters/TweakableBlockCipherParameters.cs
@@ -0,0 +1,40 @@
+using System;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+
+ /// <summary>
+ /// Parameters for tweakable block ciphers.
+ /// </summary>
+ public class TweakableBlockCipherParameters
+ : ICipherParameters
+ {
+ private readonly byte[] tweak;
+ private readonly KeyParameter key;
+
+ public TweakableBlockCipherParameters(KeyParameter key, byte[] tweak)
+ {
+ this.key = key;
+ this.tweak = Arrays.Clone(tweak);
+ }
+
+ /// <summary>
+ /// Gets the key.
+ /// </summary>
+ /// <value>the key to use, or <code>null</code> to use the current key.</value>
+ public KeyParameter Key
+ {
+ get { return key; }
+ }
+
+ /// <summary>
+ /// Gets the tweak value.
+ /// </summary>
+ /// <value>The tweak to use, or <code>null</code> to use the current tweak.</value>
+ public byte[] Tweak
+ {
+ get { return tweak; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/crypto/src/util/Arrays.cs b/crypto/src/util/Arrays.cs
index 5eab42bd7..d90bbdd90 100644
--- a/crypto/src/util/Arrays.cs
+++ b/crypto/src/util/Arrays.cs
@@ -236,6 +236,30 @@ namespace Org.BouncyCastle.Utilities
}
}
+ [CLSCompliantAttribute(false)]
+ public static ulong[] Clone(
+ ulong[] data)
+ {
+ return data == null ? null : (ulong[]) data.Clone();
+ }
+
+ [CLSCompliantAttribute(false)]
+ public static ulong[] Clone(
+ ulong[] data,
+ ulong[] existing)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+ if ((existing == null) || (existing.Length != data.Length))
+ {
+ return Clone(data);
+ }
+ Array.Copy(data, 0, existing, 0, existing.Length);
+ return existing;
+ }
+
public static byte[] Copy(byte[] data, int off, int len)
{
byte[] result = new byte[len];
diff --git a/crypto/src/util/IMemoable.cs b/crypto/src/util/IMemoable.cs
new file mode 100644
index 000000000..befc10fbf
--- /dev/null
+++ b/crypto/src/util/IMemoable.cs
@@ -0,0 +1,29 @@
+using System;
+
+namespace Org.BouncyCastle.Utilities
+{
+ public interface IMemoable
+ {
+ /// <summary>
+ /// Produce a copy of this object with its configuration and in its current state.
+ /// </summary>
+ /// <remarks>
+ /// The returned object may be used simply to store the state, or may be used as a similar object
+ /// starting from the copied state.
+ /// </remarks>
+ IMemoable Copy();
+
+ /// <summary>
+ /// Restore a copied object state into this object.
+ /// </summary>
+ /// <remarks>
+ /// Implementations of this method <em>should</em> try to avoid or minimise memory allocation to perform the reset.
+ /// </remarks>
+ /// <param name="other">an object originally {@link #copy() copied} from an object of the same type as this instance.</param>
+ /// <exception cref="ClassCastException">if the provided object is not of the correct type.</exception>
+ /// <exception cref="MemoableResetException">if the <b>other</b> parameter is in some other way invalid.</exception>
+ void Reset(IMemoable other);
+ }
+
+}
+
diff --git a/crypto/src/util/MemoableResetException.cs b/crypto/src/util/MemoableResetException.cs
new file mode 100644
index 000000000..d9542dab2
--- /dev/null
+++ b/crypto/src/util/MemoableResetException.cs
@@ -0,0 +1,27 @@
+using System;
+
+namespace Org.BouncyCastle.Utilities
+{
+ /**
+ * Exception to be thrown on a failure to reset an object implementing Memoable.
+ * <p>
+ * The exception extends ClassCastException to enable users to have a single handling case,
+ * only introducing specific handling of this one if required.
+ * </p>
+ */
+ public class MemoableResetException
+ : InvalidCastException
+ {
+ /**
+ * Basic Constructor.
+ *
+ * @param msg message to be associated with this exception.
+ */
+ public MemoableResetException(string msg)
+ : base(msg)
+ {
+ }
+ }
+
+}
+
diff --git a/crypto/test/src/crypto/test/CipherTest.cs b/crypto/test/src/crypto/test/CipherTest.cs
index a893e0239..d9c085d44 100644
--- a/crypto/test/src/crypto/test/CipherTest.cs
+++ b/crypto/test/src/crypto/test/CipherTest.cs
@@ -42,7 +42,7 @@ namespace Org.BouncyCastle.Crypto.Tests
//
// state tests
//
- byte[] buf = new byte[16];
+ byte[] buf = new byte[_engine.GetBlockSize()];
try
{
diff --git a/crypto/test/src/crypto/test/DigestTest.cs b/crypto/test/src/crypto/test/DigestTest.cs
index 533e87181..930979643 100644
--- a/crypto/test/src/crypto/test/DigestTest.cs
+++ b/crypto/test/src/crypto/test/DigestTest.cs
@@ -2,6 +2,7 @@ using System;
using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.Utilities.Test;
@@ -35,9 +36,9 @@ namespace Org.BouncyCastle.Crypto.Tests
for (int i = 0; i < input.Length - 1; i++)
{
- byte[] m = toByteArray(input[i]);
+ byte[] msg = toByteArray(input[i]);
- vectorTest(digest, i, resBuf, m, Hex.Decode(results[i]));
+ vectorTest(digest, i, resBuf, msg, Hex.Decode(results[i]));
}
byte[] lastV = toByteArray(input[input.Length - 1]);
@@ -68,6 +69,45 @@ namespace Org.BouncyCastle.Crypto.Tests
{
Fail("failing second clone vector test", results[results.Length - 1], Hex.ToHexString(resBuf));
}
+
+ //
+ // memo test
+ //
+ IMemoable m = (IMemoable)digest;
+
+ digest.BlockUpdate(lastV, 0, lastV.Length/2);
+
+ // copy the Digest
+ IMemoable copy1 = m.Copy();
+ IMemoable copy2 = copy1.Copy();
+
+ digest.BlockUpdate(lastV, lastV.Length/2, lastV.Length - lastV.Length/2);
+ digest.DoFinal(resBuf, 0);
+
+ if (!AreEqual(lastDigest, resBuf))
+ {
+ Fail("failing memo vector test", results[results.Length - 1], Hex.ToHexString(resBuf));
+ }
+
+ m.Reset(copy1);
+
+ digest.BlockUpdate(lastV, lastV.Length/2, lastV.Length - lastV.Length/2);
+ digest.DoFinal(resBuf, 0);
+
+ if (!AreEqual(lastDigest, resBuf))
+ {
+ Fail("failing memo reset vector test", results[results.Length - 1], Hex.ToHexString(resBuf));
+ }
+
+ IDigest md = (IDigest)copy2;
+
+ md.BlockUpdate(lastV, lastV.Length/2, lastV.Length - lastV.Length/2);
+ md.DoFinal(resBuf, 0);
+
+ if (!AreEqual(lastDigest, resBuf))
+ {
+ Fail("failing memo copy vector test", results[results.Length - 1], Hex.ToHexString(resBuf));
+ }
}
private byte[] toByteArray(
diff --git a/crypto/test/src/crypto/test/MD2DigestTest.cs b/crypto/test/src/crypto/test/MD2DigestTest.cs
index e9d2cb88f..963a57e49 100644
--- a/crypto/test/src/crypto/test/MD2DigestTest.cs
+++ b/crypto/test/src/crypto/test/MD2DigestTest.cs
@@ -7,198 +7,61 @@ using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.Utilities.Test;
-
namespace Org.BouncyCastle.Crypto.Tests
{
- /**
+ /**
* standard vector test for MD2
* from RFC1319 by B.Kaliski of RSA Laboratories April 1992
*
*/
- [TestFixture]
- public class MD2DigestTest
- : ITest
- {
- static private string testVec1 = "";
- static private string resVec1 = "8350e5a3e24c153df2275c9f80692773";
- static private string testVec2 = "61";
- static private string resVec2 = "32ec01ec4a6dac72c0ab96fb34c0b5d1";
- static private string testVec3 = "616263";
- static private string resVec3 = "da853b0d3f88d99b30283a69e6ded6bb";
- static private string testVec4 = "6d65737361676520646967657374";
- static private string resVec4 = "ab4f496bfb2a530b219ff33031fe06b0";
- static private string testVec5 = "6162636465666768696a6b6c6d6e6f707172737475767778797a";
- static private string resVec5 = "4e8ddff3650292ab5a4108c3aa47940b";
- static private string testVec6 = "4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a30313233343536373839";
- static private string resVec6 = "da33def2a42df13975352846c30338cd";
- static private string testVec7 = "3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930";
- static private string resVec7 = "d5976f79d83d3a0dc9806c3c66f3efd8";
-
- public string Name
- {
- get { return "MD2"; }
- }
-
- public ITestResult Perform()
- {
- IDigest digest = new MD2Digest();
- byte[] resBuf = new byte[digest.GetDigestSize()];
- string resStr;
-
- //
- // test 1
- //
- byte[] bytes = Hex.Decode(testVec1);
- digest.BlockUpdate(bytes, 0, bytes.Length);
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec1.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "MD2 failing standard vector test 1"
- + SimpleTest.NewLine
- + " expected: " + resVec1
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- //
- // test 2
- //
- bytes = Hex.Decode(testVec2);
-
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec2.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "MD2 failing standard vector test 2"
- + SimpleTest.NewLine
- + " expected: " + resVec2
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- //
- // test 3
- //
- bytes = Hex.Decode(testVec3);
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec3.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "MD2 failing standard vector test 3"
- + SimpleTest.NewLine
- + " expected: " + resVec3
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- //
- // test 4
- //
-
- bytes = Hex.Decode(testVec4);
-
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec4.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "MD2 failing standard vector test 4"
- + SimpleTest.NewLine
- + " expected: " + resVec4
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
- //
- // test 5
- //
- bytes = Hex.Decode(testVec5);
-
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec5.Equals(resStr))
- {
- return new SimpleTestResult(false,
- //System.err.println(
- "MD2 failing standard vector test 5"
- + SimpleTest.NewLine
- + " expected: " + resVec5
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
- //
- // test 6
- //
- bytes = Hex.Decode(testVec6);
-
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec6.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "MD2 failing standard vector test 6"
- + SimpleTest.NewLine
- + " expected: " + resVec6
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
- //
- // test 7
- //
- bytes = Hex.Decode(testVec7);
-
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec7.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "MD2 failing standard vector test 7"
- + SimpleTest.NewLine
- + " expected: " + resVec7
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- return new SimpleTestResult(true, Name + ": Okay");
- }
+ [TestFixture]
+ public class MD2DigestTest
+ : DigestTest
+ {
+ static string[] messages =
+ {
+ "",
+ "a",
+ "abc",
+ "message digest",
+ "abcdefghijklmnopqrstuvwxyz",
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ };
+
+ static string[] digests =
+ {
+ "8350e5a3e24c153df2275c9f80692773",
+ "32ec01ec4a6dac72c0ab96fb34c0b5d1",
+ "da853b0d3f88d99b30283a69e6ded6bb",
+ "ab4f496bfb2a530b219ff33031fe06b0",
+ "4e8ddff3650292ab5a4108c3aa47940b",
+ "da33def2a42df13975352846c30338cd",
+ "d5976f79d83d3a0dc9806c3c66f3efd8"
+ };
+
+ internal MD2DigestTest()
+ : base(new MD2Digest(), messages, digests)
+ {
+ }
+
+ protected override IDigest CloneDigest(IDigest digest)
+ {
+ return new MD2Digest((MD2Digest)digest);
+ }
public static void Main(
- string[] args)
- {
- ITest test = new MD2DigestTest();
- ITestResult result = test.Perform();
-
- Console.WriteLine(result);
- }
+ string[] args)
+ {
+ RunTest(new MD2DigestTest());
+ }
[Test]
- public void TestFunction()
- {
- string resultText = Perform().ToString();
+ public void TestFunction()
+ {
+ string resultText = Perform().ToString();
Assert.AreEqual(Name + ": Okay", resultText);
- }
- }
+ }
+ }
}
diff --git a/crypto/test/src/crypto/test/MD4DigestTest.cs b/crypto/test/src/crypto/test/MD4DigestTest.cs
index 89b5d7949..a4062e92d 100644
--- a/crypto/test/src/crypto/test/MD4DigestTest.cs
+++ b/crypto/test/src/crypto/test/MD4DigestTest.cs
@@ -9,168 +9,51 @@ using Org.BouncyCastle.Utilities.Test;
namespace Org.BouncyCastle.Crypto.Tests
{
- /**
- * standard vector test for MD4 from RFC 1320.
+ /**
+ * standard vector test for MD4 from RFC 1320.
*/
- [TestFixture]
- public class MD4DigestTest
- : ITest
- {
-// static private string testVec1 = "";
- static private string resVec1 = "31d6cfe0d16ae931b73c59d7e0c089c0";
-
- static private string testVec2 = "61";
- static private string resVec2 = "bde52cb31de33e46245e05fbdbd6fb24";
-
- static private string testVec3 = "616263";
- static private string resVec3 = "a448017aaf21d8525fc10ae87aa6729d";
-
- static private string testVec4 = "3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930";
- static private string resVec4 = "e33b4ddc9c38f2199c3e7b164fcc0536";
-
- public string Name
- {
- get { return "MD4"; }
- }
-
- public ITestResult Perform()
- {
- IDigest digest = new MD4Digest();
- byte[] resBuf = new byte[digest.GetDigestSize()];
- string resStr;
-
- //
- // test 1
- //
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec1.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "MD4 failing standard vector test 1"
- + SimpleTest.NewLine
- + " expected: " + resVec1
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- //
- // test 2
- //
- byte[] bytes = Hex.Decode(testVec2);
-
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec2.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "MD4 failing standard vector test 2"
- + SimpleTest.NewLine
- + " expected: " + resVec2
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- //
- // test 3
- //
- bytes = Hex.Decode(testVec3);
-
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec3.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "MD4 failing standard vector test 3"
- + SimpleTest.NewLine
- + " expected: " + resVec3
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- //
- // test 4
- //
- bytes = Hex.Decode(testVec4);
-
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec4.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "MD4 failing standard vector test 4"
- + SimpleTest.NewLine
- + " expected: " + resVec4
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- //
- // test 5
- //
- bytes = Hex.Decode(testVec4);
-
- digest.BlockUpdate(bytes, 0, bytes.Length/2);
-
- // clone the IDigest
- IDigest d = new MD4Digest((MD4Digest)digest);
-
- digest.BlockUpdate(bytes, bytes.Length/2, bytes.Length - bytes.Length/2);
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec4.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "MD4 failing standard vector test 5"
- + SimpleTest.NewLine
- + " expected: " + resVec4
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- d.BlockUpdate(bytes, bytes.Length/2, bytes.Length - bytes.Length/2);
- d.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec4.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "MD4 failing standard vector test 5"
- + SimpleTest.NewLine
- + " expected: " + resVec4
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
- return new SimpleTestResult(true, Name + ": Okay");
- }
-
- public static void Main(
- string[] args)
- {
- ITest test = new MD4DigestTest();
- ITestResult result = test.Perform();
-
- Console.WriteLine(result);
- }
+ [TestFixture]
+ public class MD4DigestTest
+ : DigestTest
+ {
+ static private string[] messages =
+ {
+ "",
+ "a",
+ "abc",
+ "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ };
+
+ static private string[] digests =
+ {
+ "31d6cfe0d16ae931b73c59d7e0c089c0",
+ "bde52cb31de33e46245e05fbdbd6fb24",
+ "a448017aaf21d8525fc10ae87aa6729d",
+ "e33b4ddc9c38f2199c3e7b164fcc0536"
+ };
+
+ internal MD4DigestTest()
+ : base(new MD4Digest(), messages, digests)
+ {
+ }
+
+ protected override IDigest CloneDigest(IDigest digest)
+ {
+ return new MD4Digest((MD4Digest)digest);
+ }
+
+ public static void Main(
+ string[] args)
+ {
+ RunTest(new MD4DigestTest());
+ }
[Test]
- public void TestFunction()
- {
- string resultText = Perform().ToString();
-
- Assert.AreEqual(Name + ": Okay", resultText);
- }
- }
+ public void TestFunction()
+ {
+ string resultText = Perform().ToString();
+ Assert.AreEqual(Name + ": Okay", resultText);
+ }
+ }
}
diff --git a/crypto/test/src/crypto/test/MD5DigestTest.cs b/crypto/test/src/crypto/test/MD5DigestTest.cs
index b38e06391..75cc9f8a4 100644
--- a/crypto/test/src/crypto/test/MD5DigestTest.cs
+++ b/crypto/test/src/crypto/test/MD5DigestTest.cs
@@ -7,169 +7,53 @@ using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.Utilities.Test;
-
namespace Org.BouncyCastle.Crypto.Tests
{
- /// <remarks>Standard vector test for MD5 from "Handbook of Applied Cryptography", page 345.</remarks>
- [TestFixture]
- public class MD5DigestTest
- : ITest
- {
-// static private string testVec1 = "";
- static private string resVec1 = "d41d8cd98f00b204e9800998ecf8427e";
-
- static private string testVec2 = "61";
- static private string resVec2 = "0cc175b9c0f1b6a831c399e269772661";
-
- static private string testVec3 = "616263";
- static private string resVec3 = "900150983cd24fb0d6963f7d28e17f72";
-
- static private string testVec4 = "6162636465666768696a6b6c6d6e6f707172737475767778797a";
- static private string resVec4 = "c3fcd3d76192e4007dfb496cca67e13b";
-
- public string Name
- {
- get { return "MD5"; }
- }
-
- public ITestResult Perform()
- {
- IDigest digest = new MD5Digest();
- byte[] resBuf = new byte[digest.GetDigestSize()];
- string resStr;
-
- //
- // test 1
- //
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec1.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "MD5 failing standard vector test 1"
- + SimpleTest.NewLine
- + " expected: " + resVec1
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- //
- // test 2
- //
- byte[] bytes = Hex.Decode(testVec2);
-
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec2.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "MD5 failing standard vector test 2"
- + SimpleTest.NewLine
- + " expected: " + resVec2
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- //
- // test 3
- //
- bytes = Hex.Decode(testVec3);
-
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec3.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "MD5 failing standard vector test 3"
- + SimpleTest.NewLine
- + " expected: " + resVec3
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- //
- // test 4
- //
- bytes = Hex.Decode(testVec4);
-
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec4.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "MD5 failing standard vector test 4"
- + SimpleTest.NewLine
- + " expected: " + resVec4
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- //
- // test 5
- //
- bytes = Hex.Decode(testVec4);
-
- digest.BlockUpdate(bytes, 0, bytes.Length/2);
-
- // clone the IDigest
- IDigest d = new MD5Digest((MD5Digest)digest);
-
- digest.BlockUpdate(bytes, bytes.Length/2, bytes.Length - bytes.Length/2);
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec4.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "MD5 failing standard vector test 5"
- + SimpleTest.NewLine
- + " expected: " + resVec4
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- d.BlockUpdate(bytes, bytes.Length/2, bytes.Length - bytes.Length/2);
- d.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec4.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "MD5 failing standard vector test 5"
- + SimpleTest.NewLine
- + " expected: " + resVec4
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
- return new SimpleTestResult(true, Name + ": Okay");
- }
-
- public static void Main(
- string[] args)
- {
- ITest test = new MD5DigestTest();
- ITestResult result = test.Perform();
-
- Console.WriteLine(result);
- }
+ /**
+ * standard vector test for MD5 from "Handbook of Applied Cryptography", page 345.
+ */
+ [TestFixture]
+ public class MD5DigestTest
+ : DigestTest
+ {
+ static string[] messages =
+ {
+ "",
+ "a",
+ "abc",
+ "abcdefghijklmnopqrstuvwxyz"
+ };
+
+ static string[] digests =
+ {
+ "d41d8cd98f00b204e9800998ecf8427e",
+ "0cc175b9c0f1b6a831c399e269772661",
+ "900150983cd24fb0d6963f7d28e17f72",
+ "c3fcd3d76192e4007dfb496cca67e13b"
+ };
+
+ internal MD5DigestTest()
+ : base(new MD5Digest(), messages, digests)
+ {
+ }
+
+ protected override IDigest CloneDigest(IDigest digest)
+ {
+ return new MD5Digest((MD5Digest)digest);
+ }
+
+ public static void Main(
+ string[] args)
+ {
+ RunTest(new MD5DigestTest());
+ }
[Test]
- public void TestFunction()
- {
- string resultText = Perform().ToString();
-
- Assert.AreEqual(Name + ": Okay", resultText);
- }
- }
+ public void TestFunction()
+ {
+ string resultText = Perform().ToString();
+ Assert.AreEqual(Name + ": Okay", resultText);
+ }
+ }
}
diff --git a/crypto/test/src/crypto/test/RegressionTest.cs b/crypto/test/src/crypto/test/RegressionTest.cs
index 5a13a1f96..4b639005e 100644
--- a/crypto/test/src/crypto/test/RegressionTest.cs
+++ b/crypto/test/src/crypto/test/RegressionTest.cs
@@ -39,6 +39,11 @@ namespace Org.BouncyCastle.Crypto.Tests
new SkipjackTest(),
new BlowfishTest(),
new TwofishTest(),
+ new Threefish256Test(),
+ new Threefish512Test(),
+ new Threefish1024Test(),
+ new SkeinDigestTest(),
+ new SkeinMacTest(),
new Cast5Test(),
new Cast6Test(),
new Gost28147Test(),
@@ -112,6 +117,7 @@ namespace Org.BouncyCastle.Crypto.Tests
new SipHashTest(),
new Poly1305Test(),
new OcbTest(),
+ new Sm3DigestTest()
};
public static void Main(
diff --git a/crypto/test/src/crypto/test/RipeMD128DigestTest.cs b/crypto/test/src/crypto/test/RipeMD128DigestTest.cs
index 61d70f3f8..8cf0d7e0c 100644
--- a/crypto/test/src/crypto/test/RipeMD128DigestTest.cs
+++ b/crypto/test/src/crypto/test/RipeMD128DigestTest.cs
@@ -1,135 +1,74 @@
using System;
-using System.Text;
using NUnit.Framework;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Digests;
-using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.Utilities.Test;
namespace Org.BouncyCastle.Crypto.Tests
{
- /**
- * RipeMD128 IDigest Test
- */
- [TestFixture]
- public class RipeMD128DigestTest: ITest
- {
- readonly static string[] messages =
- {
- "",
- "a",
- "abc",
- "message digest",
- "abcdefghijklmnopqrstuvwxyz",
- "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
- "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
- };
-
- readonly static string[] digests = {
- "cdf26213a150dc3ecb610f18f6b38b46",
- "86be7afa339d0fc7cfc785e72f578d33",
- "c14a12199c66e4ba84636b0f69144c77",
- "9e327b3d6e523062afc1132d7df9d1b8",
- "fd2aa607f71dc8f510714922b371834e",
- "a1aa0689d0fafa2ddc22e88b49133a06",
- "d1e959eb179c911faea4624c60c5c702",
- "3f45ef194732c2dbb2c4a2c769795fa3"
- };
-
- readonly static string MillionADigest = "4a7f5723f954eba1216c9d8f6320431f";
-
- public string Name
- {
- get { return "RipeMD128"; }
- }
-
- public ITestResult Perform()
- {
- IDigest digest = new RipeMD128Digest();
- byte[] resBuf = new byte[digest.GetDigestSize()];
-
- for (int i = 0; i < messages.Length; i++)
- {
- byte[] m = Encoding.ASCII.GetBytes(messages[i]);
- digest.BlockUpdate(m, 0, m.Length);
- digest.DoFinal(resBuf, 0);
-
- if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[i])))
- {
- return new SimpleTestResult(false, Name + ": Vector " + i + " failed");
- }
- }
-
- //
- // test 2
- //
- byte[] mm = Encoding.ASCII.GetBytes(messages[messages.Length-1]);
-
- digest.BlockUpdate(mm, 0, mm.Length/2);
-
- // clone the IDigest
- IDigest d = new RipeMD128Digest((RipeMD128Digest)digest);
-
- digest.BlockUpdate(mm, mm.Length/2, mm.Length - mm.Length/2);
- digest.DoFinal(resBuf, 0);
-
- if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[digests.Length-1])))
- {
- return new SimpleTestResult(false,
- "RipeMD128 failing clone test"
- + SimpleTest.NewLine
- + " expected: " + digests[digests.Length-1]
- + SimpleTest.NewLine
- + " got : " + Hex.ToHexString(resBuf));
- }
-
- d.BlockUpdate(mm, mm.Length/2, mm.Length - mm.Length/2);
- d.DoFinal(resBuf, 0);
-
- if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[digests.Length-1])))
- {
- return new SimpleTestResult(false,
- "RipeMD128 failing clone test - part 2"
- + SimpleTest.NewLine
- + " expected: " + digests[digests.Length-1]
- + SimpleTest.NewLine
- + " got : " + Hex.ToHexString(resBuf));
- }
-
- for (int i = 0; i < 1000000; i++)
- {
- digest.Update((byte)'a');
- }
- digest.DoFinal(resBuf, 0);
-
- if (!Arrays.AreEqual(resBuf, Hex.Decode(MillionADigest)))
- {
- return new SimpleTestResult(false, Name + ": Million a's failed");
- }
-
- return new SimpleTestResult(true, Name + ": Okay");
- }
-
- public static void Main(
+ /**
+ * RIPEMD128 Digest Test
+ */
+ [TestFixture]
+ public class RipeMD128DigestTest
+ : DigestTest
+ {
+ readonly static string[] messages = {
+ "",
+ "a",
+ "abc",
+ "message digest",
+ "abcdefghijklmnopqrstuvwxyz",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ };
+
+ readonly static string[] digests = {
+ "cdf26213a150dc3ecb610f18f6b38b46",
+ "86be7afa339d0fc7cfc785e72f578d33",
+ "c14a12199c66e4ba84636b0f69144c77",
+ "9e327b3d6e523062afc1132d7df9d1b8",
+ "fd2aa607f71dc8f510714922b371834e",
+ "a1aa0689d0fafa2ddc22e88b49133a06",
+ "d1e959eb179c911faea4624c60c5c702",
+ "3f45ef194732c2dbb2c4a2c769795fa3"
+ };
+
+ readonly static String million_a_digest = "4a7f5723f954eba1216c9d8f6320431f";
+
+ internal RipeMD128DigestTest()
+ : base(new RipeMD128Digest(), messages, digests)
+ {
+ }
+
+ public override void PerformTest()
+ {
+ base.PerformTest();
+
+ millionATest(million_a_digest);
+ }
+
+ protected override IDigest CloneDigest(IDigest digest)
+ {
+ return new RipeMD128Digest((RipeMD128Digest)digest);
+ }
+
+ public static void Main(
string[] args)
- {
- ITest test = new RipeMD128DigestTest();
- ITestResult result = test.Perform();
-
- Console.WriteLine(result);
- }
+ {
+ RunTest(new RipeMD128DigestTest());
+ }
[Test]
- public void TestFunction()
- {
- string resultText = Perform().ToString();
-
- Assert.AreEqual(Name + ": Okay", resultText);
- }
- }
+ public void TestFunction()
+ {
+ string resultText = Perform().ToString();
+ Assert.AreEqual(Name + ": Okay", resultText);
+ }
+ }
}
diff --git a/crypto/test/src/crypto/test/RipeMD160DigestTest.cs b/crypto/test/src/crypto/test/RipeMD160DigestTest.cs
index 347c64d49..76f472574 100644
--- a/crypto/test/src/crypto/test/RipeMD160DigestTest.cs
+++ b/crypto/test/src/crypto/test/RipeMD160DigestTest.cs
@@ -1,135 +1,74 @@
using System;
-using System.Text;
using NUnit.Framework;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Digests;
-using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.Utilities.Test;
namespace Org.BouncyCastle.Crypto.Tests
{
- /**
- * RipeMD160 IDigest Test
- */
- [TestFixture]
- public class RipeMD160DigestTest
- : ITest
- {
- readonly static string[] messages =
- {
- "",
- "a",
- "abc",
- "message digest",
- "abcdefghijklmnopqrstuvwxyz",
- "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
- "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
- };
-
- readonly static string[] digests = {
- "9c1185a5c5e9fc54612808977ee8f548b2258d31",
- "0bdc9d2d256b3ee9daae347be6f4dc835a467ffe",
- "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc",
- "5d0689ef49d2fae572b881b123a85ffa21595f36",
- "f71c27109c692c1b56bbdceb5b9d2865b3708dbc",
- "12a053384a9c0c88e405a06c27dcf49ada62eb2b",
- "b0e20b6e3116640286ed3a87a5713079b21f5189",
- "9b752e45573d4b39f4dbd3323cab82bf63326bfb"
- };
-
- readonly static string MillionADigest = "52783243c1697bdbe16d37f97f68f08325dc1528";
-
- public string Name
- {
- get { return "RipeMD160"; }
- }
-
- public ITestResult Perform()
- {
- IDigest digest = new RipeMD160Digest();
- byte[] resBuf = new byte[digest.GetDigestSize()];
-
- for (int i = 0; i < messages.Length; i++)
- {
- byte[] m = Encoding.ASCII.GetBytes(messages[i]);
- digest.BlockUpdate(m, 0, m.Length);
- digest.DoFinal(resBuf, 0);
-
- if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[i])))
- {
- return new SimpleTestResult(false, Name + ": Vector " + i + " failed");
- }
- }
-
- //
- // test 2
- //
- byte[] mm = Encoding.ASCII.GetBytes(messages[messages.Length-1]);
-
- digest.BlockUpdate(mm, 0, mm.Length/2);
-
- // clone the IDigest
- IDigest d = new RipeMD160Digest((RipeMD160Digest)digest);
-
- digest.BlockUpdate(mm, mm.Length/2, mm.Length - mm.Length/2);
- digest.DoFinal(resBuf, 0);
-
- if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[digests.Length-1])))
- {
- return new SimpleTestResult(false,
- "RipeMD160 failing clone test"
- + SimpleTest.NewLine
- + " expected: " + digests[digests.Length-1]
- + SimpleTest.NewLine
- + " got : " + Hex.ToHexString(resBuf));
- }
-
- d.BlockUpdate(mm, mm.Length/2, mm.Length - mm.Length/2);
- d.DoFinal(resBuf, 0);
-
- if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[digests.Length-1])))
- {
- return new SimpleTestResult(false,
- "RipeMD160 failing clone test - part 2"
- + SimpleTest.NewLine
- + " expected: " + digests[digests.Length-1]
- + SimpleTest.NewLine
- + " got : " + Hex.ToHexString(resBuf));
- }
-
- for (int i = 0; i < 1000000; i++)
- {
- digest.Update((byte)'a');
- }
- digest.DoFinal(resBuf, 0);
-
- if (!Arrays.AreEqual(resBuf, Hex.Decode(MillionADigest)))
- {
- return new SimpleTestResult(false, Name + ": Million a's failed");
- }
-
- return new SimpleTestResult(true, Name + ": Okay");
- }
+ /**
+ * RIPEMD160 Digest Test
+ */
+ [TestFixture]
+ public class RipeMD160DigestTest
+ : DigestTest
+ {
+ readonly static string[] messages = {
+ "",
+ "a",
+ "abc",
+ "message digest",
+ "abcdefghijklmnopqrstuvwxyz",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ };
+
+ readonly static string[] digests = {
+ "9c1185a5c5e9fc54612808977ee8f548b2258d31",
+ "0bdc9d2d256b3ee9daae347be6f4dc835a467ffe",
+ "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc",
+ "5d0689ef49d2fae572b881b123a85ffa21595f36",
+ "f71c27109c692c1b56bbdceb5b9d2865b3708dbc",
+ "12a053384a9c0c88e405a06c27dcf49ada62eb2b",
+ "b0e20b6e3116640286ed3a87a5713079b21f5189",
+ "9b752e45573d4b39f4dbd3323cab82bf63326bfb"
+ };
+
+ readonly static string million_a_digest = "52783243c1697bdbe16d37f97f68f08325dc1528";
+
+ internal RipeMD160DigestTest()
+ : base(new RipeMD160Digest(), messages, digests)
+ {
+ }
+
+ public override void PerformTest()
+ {
+ base.PerformTest();
+
+ millionATest(million_a_digest);
+ }
+
+ protected override IDigest CloneDigest(IDigest digest)
+ {
+ return new RipeMD160Digest((RipeMD160Digest)digest);
+ }
public static void Main(
string[] args)
- {
- ITest test = new RipeMD160DigestTest();
- ITestResult result = test.Perform();
-
- Console.WriteLine(result);
- }
+ {
+ RunTest(new RipeMD160DigestTest());
+ }
- [Test]
- public void TestFunction()
- {
- string resultText = Perform().ToString();
+ [Test]
+ public void TestFunction()
+ {
+ string resultText = Perform().ToString();
Assert.AreEqual(Name + ": Okay", resultText);
- }
- }
+ }
+ }
}
diff --git a/crypto/test/src/crypto/test/RipeMD256DigestTest.cs b/crypto/test/src/crypto/test/RipeMD256DigestTest.cs
index 909200d64..27a9c88cc 100644
--- a/crypto/test/src/crypto/test/RipeMD256DigestTest.cs
+++ b/crypto/test/src/crypto/test/RipeMD256DigestTest.cs
@@ -1,97 +1,67 @@
using System;
-using System.Text;
using NUnit.Framework;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Digests;
-using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.Utilities.Test;
namespace Org.BouncyCastle.Crypto.Tests
{
- /// <summary> RipeMD256 IDigest Test</summary>
- [TestFixture]
- public class RipeMD256DigestTest
- : ITest
- {
- public string Name
- {
- get { return "RipeMD256"; }
- }
-
- internal static readonly string[] messages = new string[]{"", "a", "abc", "message digest", "abcdefghijklmnopqrstuvwxyz", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "12345678901234567890123456789012345678901234567890123456789012345678901234567890"};
-
- internal static readonly string[] digests = new string[]{"02ba4c4e5f8ecd1877fc52d64d30e37a2d9774fb1e5d026380ae0168e3c5522d", "f9333e45d857f5d90a91bab70a1eba0cfb1be4b0783c9acfcd883a9134692925", "afbd6e228b9d8cbbcef5ca2d03e6dba10ac0bc7dcbe4680e1e42d2e975459b65", "87e971759a1ce47a514d5c914c392c9018c7c46bc14465554afcdf54a5070c0e", "649d3034751ea216776bf9a18acc81bc7896118a5197968782dd1fd97d8d5133", "3843045583aac6c8c8d9128573e7a9809afb2a0f34ccc36ea9e72f16f6368e3f", "5740a408ac16b720b84424ae931cbb1fe363d1d0bf4017f1a89f7ea6de77a0b8", "06fdcc7a409548aaf91368c06a6275b553e3f099bf0ea4edfd6778df89a890dd"};
-
- internal const string MillionADigest = "ac953744e10e31514c150d4d8d7b677342e33399788296e43ae4850ce4f97978";
-
- public virtual ITestResult Perform()
- {
- IDigest digest = new RipeMD256Digest();
- byte[] resBuf = new byte[digest.GetDigestSize()];
-
- for (int i = 0; i < messages.Length; i++)
- {
- byte[] m = Encoding.ASCII.GetBytes(messages[i]);
- digest.BlockUpdate(m, 0, m.Length);
- digest.DoFinal(resBuf, 0);
-
- if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[i])))
- {
- return new SimpleTestResult(false, Name + ": Vector " + i + " failed" + " expected: " + digests[i] + SimpleTest.NewLine + " got : " + Hex.ToHexString(resBuf));
- }
- }
-
- //
- // test 2
- //
- byte[] m2 = Encoding.ASCII.GetBytes(messages[messages.Length - 1]);
- digest.BlockUpdate(m2, 0, m2.Length / 2);
-
- // clone the IDigest
- IDigest d = new RipeMD256Digest((RipeMD256Digest) digest);
-
- digest.BlockUpdate(m2, m2.Length / 2, m2.Length - m2.Length / 2);
- digest.DoFinal(resBuf, 0);
-
- if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[digests.Length - 1])))
- {
- return new SimpleTestResult(false, "RipeMD256 failing clone test" + SimpleTest.NewLine + " expected: " + digests[digests.Length - 1] + SimpleTest.NewLine + " got : " + Hex.ToHexString(resBuf));
- }
-
- d.BlockUpdate(m2, m2.Length / 2, m2.Length - m2.Length / 2);
- d.DoFinal(resBuf, 0);
-
- if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[digests.Length - 1])))
- {
- return new SimpleTestResult(false, "RipeMD256 failing clone test - part 2" + SimpleTest.NewLine + " expected: " + digests[digests.Length - 1] + SimpleTest.NewLine + " got : " + Hex.ToHexString(resBuf));
- }
-
- for (int i = 0; i < 1000000; i++)
- {
- digest.Update((byte) 'a');
- }
+ /**
+ * RIPEMD256 Digest Test
+ */
+ [TestFixture]
+ public class RipeMD256DigestTest
+ : DigestTest
+ {
+ readonly static string[] messages = {
+ "",
+ "a",
+ "abc",
+ "message digest",
+ "abcdefghijklmnopqrstuvwxyz",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ };
+
+ readonly static string[] digests = {
+ "02ba4c4e5f8ecd1877fc52d64d30e37a2d9774fb1e5d026380ae0168e3c5522d",
+ "f9333e45d857f5d90a91bab70a1eba0cfb1be4b0783c9acfcd883a9134692925",
+ "afbd6e228b9d8cbbcef5ca2d03e6dba10ac0bc7dcbe4680e1e42d2e975459b65",
+ "87e971759a1ce47a514d5c914c392c9018c7c46bc14465554afcdf54a5070c0e",
+ "649d3034751ea216776bf9a18acc81bc7896118a5197968782dd1fd97d8d5133",
+ "3843045583aac6c8c8d9128573e7a9809afb2a0f34ccc36ea9e72f16f6368e3f",
+ "5740a408ac16b720b84424ae931cbb1fe363d1d0bf4017f1a89f7ea6de77a0b8",
+ "06fdcc7a409548aaf91368c06a6275b553e3f099bf0ea4edfd6778df89a890dd"
+ };
+
+ readonly static string million_a_digest = "ac953744e10e31514c150d4d8d7b677342e33399788296e43ae4850ce4f97978";
+
+ internal RipeMD256DigestTest()
+ : base(new RipeMD256Digest(), messages, digests)
+ {
+ }
- digest.DoFinal(resBuf, 0);
+ public override void PerformTest()
+ {
+ base.PerformTest();
- if (!Arrays.AreEqual(resBuf, Hex.Decode(MillionADigest)))
- {
- return new SimpleTestResult(false, Name + ": Million a's failed");
- }
+ millionATest(million_a_digest);
+ }
- return new SimpleTestResult(true, Name + ": Okay");
- }
+ protected override IDigest CloneDigest(IDigest digest)
+ {
+ return new RipeMD256Digest((RipeMD256Digest)digest);
+ }
public static void Main(
string[] args)
- {
- ITest test = new RipeMD256DigestTest();
- ITestResult result = test.Perform();
-
- Console.WriteLine(result);
- }
+ {
+ RunTest(new RipeMD256DigestTest());
+ }
[Test]
public void TestFunction()
@@ -100,5 +70,5 @@ namespace Org.BouncyCastle.Crypto.Tests
Assert.AreEqual(Name + ": Okay", resultText);
}
- }
+ }
}
diff --git a/crypto/test/src/crypto/test/RipeMD320DigestTest.cs b/crypto/test/src/crypto/test/RipeMD320DigestTest.cs
index 253cb9d9a..51296e55b 100644
--- a/crypto/test/src/crypto/test/RipeMD320DigestTest.cs
+++ b/crypto/test/src/crypto/test/RipeMD320DigestTest.cs
@@ -1,105 +1,74 @@
using System;
-using System.Text;
using NUnit.Framework;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Digests;
-using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.Utilities.Test;
namespace Org.BouncyCastle.Crypto.Tests
{
- /// <summary> RipeMD320 IDigest Test</summary>
- [TestFixture]
- public class RipeMD320DigestTest
- : ITest
- {
- public string Name
- {
- get { return "RipeMD320"; }
- }
-
- internal static readonly string[] messages = new string[]{"", "a", "abc", "message digest", "abcdefghijklmnopqrstuvwxyz", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "12345678901234567890123456789012345678901234567890123456789012345678901234567890"};
-
- internal static readonly string[] digests = new string[]{"22d65d5661536cdc75c1fdf5c6de7b41b9f27325ebc61e8557177d705a0ec880151c3a32a00899b8", "ce78850638f92658a5a585097579926dda667a5716562cfcf6fbe77f63542f99b04705d6970dff5d", "de4c01b3054f8930a79d09ae738e92301e5a17085beffdc1b8d116713e74f82fa942d64cdbc4682d", "3a8e28502ed45d422f68844f9dd316e7b98533fa3f2a91d29f84d425c88d6b4eff727df66a7c0197", "cabdb1810b92470a2093aa6bce05952c28348cf43ff60841975166bb40ed234004b8824463e6b009", "d034a7950cf722021ba4b84df769a5de2060e259df4c9bb4a4268c0e935bbc7470a969c9d072a1ac", "ed544940c86d67f250d232c30b7b3e5770e0c60c8cb9a4cafe3b11388af9920e1b99230b843c86a4", "557888af5f6d8ed62ab66945c6d2a0a47ecd5341e915eb8fea1d0524955f825dc717e4a008ab2d42"};
-
- internal const string MillionADigest = "bdee37f4371e20646b8b0d862dda16292ae36f40965e8c8509e63d1dbddecc503e2b63eb9245bb66";
-
- public virtual ITestResult Perform()
- {
- IDigest digest = new RipeMD320Digest();
- byte[] resBuf = new byte[digest.GetDigestSize()];
-
- for (int i = 0; i < messages.Length; i++)
- {
- byte[] m = Encoding.ASCII.GetBytes(messages[i]);
- digest.BlockUpdate(m, 0, m.Length);
- digest.DoFinal(resBuf, 0);
-
- if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[i])))
- {
- Console.WriteLine(Name + ": Vector " + i + " failed" + " expected: " + digests[i] + SimpleTest.NewLine + " got : " + Hex.ToHexString(resBuf));
- return new SimpleTestResult(false, Name + ": Vector " + i + " failed");
- }
- }
-
- //
- // test 2
- //
- byte[] m2 = Encoding.ASCII.GetBytes(messages[messages.Length - 1]);
-
- digest.BlockUpdate(m2, 0, m2.Length / 2);
-
- // clone the IDigest
- IDigest d = new RipeMD320Digest((RipeMD320Digest) digest);
-
- digest.BlockUpdate(m2, m2.Length / 2, m2.Length - m2.Length / 2);
- digest.DoFinal(resBuf, 0);
-
- if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[digests.Length - 1])))
- {
- return new SimpleTestResult(false, "RipeMD320 failing clone test" + SimpleTest.NewLine + " expected: " + digests[digests.Length - 1] + SimpleTest.NewLine + " got : " + Hex.ToHexString(resBuf));
- }
-
- d.BlockUpdate(m2, m2.Length / 2, m2.Length - m2.Length / 2);
- d.DoFinal(resBuf, 0);
-
- if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[digests.Length - 1])))
- {
- return new SimpleTestResult(false, "RipeMD320 failing clone test - part 2" + SimpleTest.NewLine + " expected: " + digests[digests.Length - 1] + SimpleTest.NewLine + " got : " + Hex.ToHexString(resBuf));
- }
-
- for (int i = 0; i < 1000000; i++)
- {
- digest.Update((byte) 'a');
- }
- digest.DoFinal(resBuf, 0);
-
- if (!Arrays.AreEqual(resBuf, Hex.Decode(MillionADigest)))
- {
- return new SimpleTestResult(false, Name + ": Million a's failed");
- }
-
- return new SimpleTestResult(true, Name + ": Okay");
- }
-
- public static void Main(
+ /**
+ * RIPEMD320 Digest Test
+ */
+ [TestFixture]
+ public class RipeMD320DigestTest
+ : DigestTest
+ {
+ readonly static string[] messages = {
+ "",
+ "a",
+ "abc",
+ "message digest",
+ "abcdefghijklmnopqrstuvwxyz",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ };
+
+ readonly static string[] digests = {
+ "22d65d5661536cdc75c1fdf5c6de7b41b9f27325ebc61e8557177d705a0ec880151c3a32a00899b8",
+ "ce78850638f92658a5a585097579926dda667a5716562cfcf6fbe77f63542f99b04705d6970dff5d",
+ "de4c01b3054f8930a79d09ae738e92301e5a17085beffdc1b8d116713e74f82fa942d64cdbc4682d",
+ "3a8e28502ed45d422f68844f9dd316e7b98533fa3f2a91d29f84d425c88d6b4eff727df66a7c0197",
+ "cabdb1810b92470a2093aa6bce05952c28348cf43ff60841975166bb40ed234004b8824463e6b009",
+ "d034a7950cf722021ba4b84df769a5de2060e259df4c9bb4a4268c0e935bbc7470a969c9d072a1ac",
+ "ed544940c86d67f250d232c30b7b3e5770e0c60c8cb9a4cafe3b11388af9920e1b99230b843c86a4",
+ "557888af5f6d8ed62ab66945c6d2a0a47ecd5341e915eb8fea1d0524955f825dc717e4a008ab2d42"
+ };
+
+ readonly static string million_a_digest = "bdee37f4371e20646b8b0d862dda16292ae36f40965e8c8509e63d1dbddecc503e2b63eb9245bb66";
+
+ internal RipeMD320DigestTest()
+ : base(new RipeMD320Digest(), messages, digests)
+ {
+ }
+
+ public override void PerformTest()
+ {
+ base.PerformTest();
+
+ millionATest(million_a_digest);
+ }
+
+ protected override IDigest CloneDigest(IDigest digest)
+ {
+ return new RipeMD320Digest((RipeMD320Digest)digest);
+ }
+
+ public static void Main(
string[] args)
- {
- ITest test = new RipeMD320DigestTest();
- ITestResult result = test.Perform();
-
- Console.WriteLine(result);
- }
+ {
+ RunTest(new RipeMD320DigestTest());
+ }
[Test]
- public void TestFunction()
- {
- string resultText = Perform().ToString();
+ public void TestFunction()
+ {
+ string resultText = Perform().ToString();
- Assert.AreEqual(Name + ": Okay", resultText);
- }
- }
+ Assert.AreEqual(Name + ": Okay", resultText);
+ }
+ }
}
diff --git a/crypto/test/src/crypto/test/SHA1DigestTest.cs b/crypto/test/src/crypto/test/SHA1DigestTest.cs
index 22a5c8f46..8e0564dd8 100644
--- a/crypto/test/src/crypto/test/SHA1DigestTest.cs
+++ b/crypto/test/src/crypto/test/SHA1DigestTest.cs
@@ -12,126 +12,32 @@ namespace Org.BouncyCastle.Crypto.Tests
/// <remarks>Standard vector test for SHA-1 from "Handbook of Applied Cryptography", page 345.</remarks>
[TestFixture]
public class Sha1DigestTest
- : SimpleTest
+ : DigestTest
{
- //static private string testVec1 = "";
- static private string resVec1 = "da39a3ee5e6b4b0d3255bfef95601890afd80709";
-
- static private string testVec2 = "61";
- static private string resVec2 = "86f7e437faa5a7fce15d1ddcb9eaeaea377667b8";
-
- static private string testVec3 = "616263";
- static private string resVec3 = "a9993e364706816aba3e25717850c26c9cd0d89d";
-
- static private string testVec4 = "6162636465666768696a6b6c6d6e6f707172737475767778797a";
- static private string resVec4 = "32d10c7b8cf96570ca04ce37f2a19d84240d3a89";
+ private static string[] messages =
+ {
+ "",
+ "a",
+ "abc",
+ "abcdefghijklmnopqrstuvwxyz"
+ };
- public override string Name
+ private static string[] digests =
+ {
+ "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+ "86f7e437faa5a7fce15d1ddcb9eaeaea377667b8",
+ "a9993e364706816aba3e25717850c26c9cd0d89d",
+ "32d10c7b8cf96570ca04ce37f2a19d84240d3a89"
+ };
+
+ internal Sha1DigestTest()
+ : base(new Sha1Digest(), messages, digests)
{
- get { return "SHA1"; }
}
- public override void PerformTest()
+ protected override IDigest CloneDigest(IDigest digest)
{
- IDigest digest = new Sha1Digest();
- byte[] resBuf = new byte[digest.GetDigestSize()];
- string resStr;
-
- //
- // test 1
- //
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec1.Equals(resStr))
- {
- Fail("failing standard vector test 1" + SimpleTest.NewLine
- + " expected: " + resVec1 + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- //
- // test 2
- //
- byte[] bytes = Hex.Decode(testVec2);
-
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec2.Equals(resStr))
- {
- Fail("failing standard vector test 2" + SimpleTest.NewLine
- + " expected: " + resVec2 + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- //
- // test 3
- //
- bytes = Hex.Decode(testVec3);
-
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec3.Equals(resStr))
- {
- Fail("failing standard vector test 3" + SimpleTest.NewLine
- + " expected: " + resVec3 + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- //
- // test 4
- //
- bytes = Hex.Decode(testVec4);
-
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec4.Equals(resStr))
- {
- Fail("failing standard vector test 4" + SimpleTest.NewLine
- + " expected: " + resVec4 + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- //
- // test 5
- //
- bytes = Hex.Decode(testVec4);
-
- digest.BlockUpdate(bytes, 0, bytes.Length / 2);
-
- // clone the IDigest
- IDigest d = new Sha1Digest((Sha1Digest)digest);
-
- digest.BlockUpdate(bytes, bytes.Length / 2, bytes.Length - bytes.Length / 2);
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec4.Equals(resStr))
- {
- Fail("failing standard vector test 5" + SimpleTest.NewLine
- + " expected: " + resVec4 + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- d.BlockUpdate(bytes, bytes.Length / 2, bytes.Length - bytes.Length / 2);
- d.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec4.Equals(resStr))
- {
- Fail("failing standard vector test 5" + SimpleTest.NewLine
- + " expected: " + resVec4 + SimpleTest.NewLine
- + " got : " + resStr);
- }
+ return new Sha1Digest((Sha1Digest)digest);
}
public static void Main(
diff --git a/crypto/test/src/crypto/test/SHA224DigestTest.cs b/crypto/test/src/crypto/test/SHA224DigestTest.cs
index 37035c30f..8207a18c7 100644
--- a/crypto/test/src/crypto/test/SHA224DigestTest.cs
+++ b/crypto/test/src/crypto/test/SHA224DigestTest.cs
@@ -9,192 +9,62 @@ using Org.BouncyCastle.Utilities.Test;
namespace Org.BouncyCastle.Crypto.Tests
{
- /**
- * standard vector test for SHA-224 from RFC 3874 - only the last three are in
- * the RFC.
- */
- [TestFixture]
- public class Sha224DigestTest
- : ITest
- {
- private const string testVec1 = "";
- private const string resVec1 = "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f";
-
- private const string testVec2 = "61";
- private const string resVec2 = "abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5";
-
- private const string testVec3 = "616263";
- private const string resVec3 = "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7";
-
- private const string testVec4 = "6162636462636465636465666465666765666768666768696768696a68696a6b696a6b6c6a6b6c6d6b6c6d6e6c6d6e6f6d6e6f706e6f7071";
- private const string resVec4 = "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525";
+ /**
+ * standard vector test for SHA-224 from RFC 3874 - only the last three are in
+ * the RFC.
+ */
+ [TestFixture]
+ public class Sha224DigestTest
+ : DigestTest
+ {
+ private static string[] messages =
+ {
+ "",
+ "a",
+ "abc",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ };
+
+ private static string[] digests =
+ {
+ "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f",
+ "abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5",
+ "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7",
+ "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525"
+ };
// 1 million 'a'
- private const string testVec5 = "61616161616161616161";
- private const string resVec5 = "20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67";
-
- public string Name
- {
- get { return "SHA224"; }
- }
-
- public ITestResult Perform()
- {
- IDigest digest = new Sha224Digest();
- byte[] resBuf = new byte[digest.GetDigestSize()];
- string resStr;
-
- //
- // test 1
- //
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec1.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "SHA-224 failing standard vector test 1"
- + SimpleTest.NewLine
- + " expected: " + resVec1
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- //
- // test 2
- //
- byte[] bytes = Hex.Decode(testVec2);
-
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec2.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "SHA-224 failing standard vector test 2"
- + SimpleTest.NewLine
- + " expected: " + resVec2
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- //
- // test 3
- //
- bytes = Hex.Decode(testVec3);
-
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec3.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "SHA-224 failing standard vector test 3"
- + SimpleTest.NewLine
- + " expected: " + resVec3
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- //
- // test 4
- //
- bytes = Hex.Decode(testVec4);
-
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec4.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "SHA-224 failing standard vector test 4"
- + SimpleTest.NewLine
- + " expected: " + resVec4
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- //
- // test 5
- //
- bytes = Hex.Decode(testVec4);
-
- digest.BlockUpdate(bytes, 0, bytes.Length/2);
-
- // clone the IDigest
- IDigest d = new Sha224Digest((Sha224Digest)digest);
-
- digest.BlockUpdate(bytes, bytes.Length/2, bytes.Length - bytes.Length/2);
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec4.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "SHA-224 failing standard vector test 5"
- + SimpleTest.NewLine
- + " expected: " + resVec4
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- d.BlockUpdate(bytes, bytes.Length/2, bytes.Length - bytes.Length/2);
- d.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec4.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "SHA-224 failing standard vector test 5"
- + SimpleTest.NewLine
- + " expected: " + resVec4
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
+ private static string million_a_digest = "20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67";
- // test 6
- bytes = Hex.Decode(testVec5);
- for ( int i = 0; i < 100000; i++ )
- {
- digest.BlockUpdate(bytes, 0, bytes.Length);
- }
- digest.DoFinal(resBuf, 0);
+ internal Sha224DigestTest()
+ : base(new Sha224Digest(), messages, digests)
+ {
+ }
- resStr = Hex.ToHexString(resBuf);
- if (!resVec5.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "SHA-224 failing standard vector test 6"
- + SimpleTest.NewLine
- + " expected: " + resVec5
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
+ public override void PerformTest()
+ {
+ base.PerformTest();
- return new SimpleTestResult(true, Name + ": Okay");
- }
+ millionATest(million_a_digest);
+ }
- public static void Main(
- string[] args)
- {
- ITest test = new Sha224DigestTest();
- ITestResult result = test.Perform();
+ protected override IDigest CloneDigest(IDigest digest)
+ {
+ return new Sha224Digest((Sha224Digest)digest);
+ }
- Console.WriteLine(result);
- }
+ public static void Main(
+ string[] args)
+ {
+ RunTest(new Sha224DigestTest());
+ }
[Test]
- public void TestFunction()
- {
- string resultText = Perform().ToString();
+ public void TestFunction()
+ {
+ string resultText = Perform().ToString();
Assert.AreEqual(Name + ": Okay", resultText);
- }
- }
+ }
+ }
}
diff --git a/crypto/test/src/crypto/test/SHA256DigestTest.cs b/crypto/test/src/crypto/test/SHA256DigestTest.cs
index 67f0c2397..d4d29ccbb 100644
--- a/crypto/test/src/crypto/test/SHA256DigestTest.cs
+++ b/crypto/test/src/crypto/test/SHA256DigestTest.cs
@@ -4,202 +4,68 @@ using NUnit.Framework;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Digests;
-using Org.BouncyCastle.Crypto.Engines;
-using Org.BouncyCastle.Crypto.Encodings;
-using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.Utilities.Test;
namespace Org.BouncyCastle.Crypto.Tests
{
- /**
+ /**
* standard vector test for SHA-256 from FIPS Draft 180-2.
*
* Note, the first two vectors are _not_ from the draft, the last three are.
*/
- [TestFixture]
- public class Sha256DigestTest
- : ITest
- {
-// static private string testVec1 = "";
- static private string resVec1 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
-
- static private string testVec2 = "61";
- static private string resVec2 = "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb";
-
- static private string testVec3 = "616263";
- static private string resVec3 = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad";
-
- static private string testVec4 = "6162636462636465636465666465666765666768666768696768696a68696a6b696a6b6c6a6b6c6d6b6c6d6e6c6d6e6f6d6e6f706e6f7071";
- static private string resVec4 = "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1";
-
- // 1 million 'a'
- static private string testVec5 = "61616161616161616161";
- static private string resVec5 = "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0";
-
- public string Name
- {
- get { return "SHA256"; }
- }
-
- public ITestResult Perform()
- {
- IDigest digest = new Sha256Digest();
- byte[] resBuf = new byte[digest.GetDigestSize()];
- string resStr;
-
- //
- // test 1
- //
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec1.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "SHA-256 failing standard vector test 1"
- + SimpleTest.NewLine
- + " expected: " + resVec1
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- //
- // test 2
- //
- byte[] bytes = Hex.Decode(testVec2);
-
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec2.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "SHA-256 failing standard vector test 2"
- + SimpleTest.NewLine
- + " expected: " + resVec2
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- //
- // test 3
- //
- bytes = Hex.Decode(testVec3);
-
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec3.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "SHA-256 failing standard vector test 3"
- + SimpleTest.NewLine
- + " expected: " + resVec3
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- //
- // test 4
- //
- bytes = Hex.Decode(testVec4);
-
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec4.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "SHA-256 failing standard vector test 4"
- + SimpleTest.NewLine
- + " expected: " + resVec4
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- //
- // test 5
- //
- bytes = Hex.Decode(testVec4);
-
- digest.BlockUpdate(bytes, 0, bytes.Length/2);
-
- // clone the IDigest
- IDigest d = new Sha256Digest((Sha256Digest)digest);
-
- digest.BlockUpdate(bytes, bytes.Length/2, bytes.Length - bytes.Length/2);
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec4.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "SHA-256 failing standard vector test 5"
- + SimpleTest.NewLine
- + " expected: " + resVec4
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- d.BlockUpdate(bytes, bytes.Length/2, bytes.Length - bytes.Length/2);
- d.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec4.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "SHA-256 failing standard vector test 5"
- + SimpleTest.NewLine
- + " expected: " + resVec4
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- // test 6
- bytes = Hex.Decode(testVec5);
- for ( int i = 0; i < 100000; i++ )
- {
- digest.BlockUpdate(bytes, 0, bytes.Length);
- }
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec5.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "SHA-256 failing standard vector test 6"
- + SimpleTest.NewLine
- + " expected: " + resVec5
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- return new SimpleTestResult(true, Name + ": Okay");
- }
+ [TestFixture]
+ public class Sha256DigestTest
+ : DigestTest
+ {
+ private static string[] messages =
+ {
+ "",
+ "a",
+ "abc",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ };
+
+ private static string[] digests =
+ {
+ "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb",
+ "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
+ "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"
+ };
+
+ // 1 million 'a'
+ static private string million_a_digest = "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0";
+
+ internal Sha256DigestTest()
+ : base(new Sha256Digest(), messages, digests)
+ {
+ }
+
+ public override void PerformTest()
+ {
+ base.PerformTest();
+
+ millionATest(million_a_digest);
+ }
+
+ protected override IDigest CloneDigest(IDigest digest)
+ {
+ return new Sha256Digest((Sha256Digest)digest);
+ }
public static void Main(
string[] args)
- {
- ITest test = new Sha256DigestTest();
- ITestResult result = test.Perform();
-
- Console.WriteLine(result);
- }
+ {
+ RunTest(new Sha256DigestTest());
+ }
[Test]
- public void TestFunction()
- {
- string resultText = Perform().ToString();
-
- Assert.AreEqual(Name + ": Okay", resultText);
- }
- }
+ public void TestFunction()
+ {
+ string resultText = Perform().ToString();
+ Assert.AreEqual(Name + ": Okay", resultText);
+ }
+ }
}
diff --git a/crypto/test/src/crypto/test/SHA384DigestTest.cs b/crypto/test/src/crypto/test/SHA384DigestTest.cs
index 70c26edcc..ae9ad0c17 100644
--- a/crypto/test/src/crypto/test/SHA384DigestTest.cs
+++ b/crypto/test/src/crypto/test/SHA384DigestTest.cs
@@ -4,200 +4,67 @@ using NUnit.Framework;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Digests;
-using Org.BouncyCastle.Crypto.Engines;
-using Org.BouncyCastle.Crypto.Encodings;
-using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.Utilities.Test;
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 Sha384DigestTest
- : ITest
- {
-// static private string testVec1 = "";
- static private string resVec1 = "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b";
-
- static private string testVec2 = "61";
- static private string resVec2 = "54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31";
-
- static private string testVec3 = "616263";
- static private string resVec3 = "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7";
-
- static private string testVec4 = "61626364656667686263646566676869636465666768696a6465666768696a6b65666768696a6b6c666768696a6b6c6d6768696a6b6c6d6e68696a6b6c6d6e6f696a6b6c6d6e6f706a6b6c6d6e6f70716b6c6d6e6f7071726c6d6e6f707172736d6e6f70717273746e6f707172737475";
- static private string resVec4 = "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039";
-
- // 1 million 'a'
- static private string testVec5 = "61616161616161616161";
- static private string resVec5 = "9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985";
-
- public string Name
- {
- get { return "SHA384"; }
- }
-
- public ITestResult Perform()
- {
- IDigest digest = new Sha384Digest();
- byte[] resBuf = new byte[digest.GetDigestSize()];
- string resStr;
-
- //
- // test 1
- //
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec1.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "SHA-384 failing standard vector test 1"
- + SimpleTest.NewLine
- + " expected: " + resVec1
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- //
- // test 2
- //
- byte[] bytes = Hex.Decode(testVec2);
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec2.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "SHA-384 failing standard vector test 2"
- + SimpleTest.NewLine
- + " expected: " + resVec2
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- //
- // test 3
- //
- bytes = Hex.Decode(testVec3);
-
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec3.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "SHA-384 failing standard vector test 3"
- + SimpleTest.NewLine
- + " expected: " + resVec3
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- //
- // test 4
- //
- bytes = Hex.Decode(testVec4);
-
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec4.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "SHA-384 failing standard vector test 4"
- + SimpleTest.NewLine
- + " expected: " + resVec4
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- //
- // test 5
- //
- bytes = Hex.Decode(testVec4);
-
- digest.BlockUpdate(bytes, 0, bytes.Length/2);
-
- // clone the IDigest
- IDigest d = new Sha384Digest((Sha384Digest)digest);
-
- digest.BlockUpdate(bytes, bytes.Length/2, bytes.Length - bytes.Length/2);
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec4.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "SHA-384 failing standard vector test 5"
- + SimpleTest.NewLine
- + " expected: " + resVec4
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- d.BlockUpdate(bytes, bytes.Length/2, bytes.Length - bytes.Length/2);
- d.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec4.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "SHA-384 failing standard vector test 5"
- + SimpleTest.NewLine
- + " expected: " + resVec4
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- // test 6
- bytes = Hex.Decode(testVec5);
- for ( int i = 0; i < 100000; i++ )
- {
- digest.BlockUpdate(bytes, 0, bytes.Length);
- }
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec5.Equals(resStr))
- {
- return new SimpleTestResult(false,
- "SHA-384 failing standard vector test 6"
- + SimpleTest.NewLine
- + " expected: " + resVec5
- + SimpleTest.NewLine
- + " got : " + resStr);
- }
-
- return new SimpleTestResult(true, Name + ": Okay");
- }
-
- public static void Main(
- string[] args)
- {
- ITest test = new Sha384DigestTest();
- ITestResult result = test.Perform();
-
- Console.WriteLine(result);
- }
+ [TestFixture]
+ public class Sha384DigestTest
+ : DigestTest
+ {
+ private static string[] messages =
+ {
+ "",
+ "a",
+ "abc",
+ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
+ };
+
+ private static string[] digests =
+ {
+ "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b",
+ "54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31",
+ "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7",
+ "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039"
+ };
+
+ static private string million_a_digest = "9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985";
+
+ internal Sha384DigestTest()
+ : base(new Sha384Digest(), messages, digests)
+ {
+ }
+
+ public override void PerformTest()
+ {
+ base.PerformTest();
+
+ millionATest(million_a_digest);
+ }
+
+ protected override IDigest CloneDigest(IDigest digest)
+ {
+ return new Sha384Digest((Sha384Digest)digest);
+ }
+
+ public static void Main(
+ string[] args)
+ {
+ RunTest(new Sha384DigestTest());
+ }
[Test]
- public void TestFunction()
- {
- string resultText = Perform().ToString();
+ public void TestFunction()
+ {
+ string resultText = Perform().ToString();
Assert.AreEqual(Name + ": Okay", resultText);
- }
- }
+ }
+ }
}
diff --git a/crypto/test/src/crypto/test/SHA512DigestTest.cs b/crypto/test/src/crypto/test/SHA512DigestTest.cs
index c8096b7db..814500b63 100644
--- a/crypto/test/src/crypto/test/SHA512DigestTest.cs
+++ b/crypto/test/src/crypto/test/SHA512DigestTest.cs
@@ -9,157 +9,62 @@ using Org.BouncyCastle.Utilities.Test;
namespace Org.BouncyCastle.Crypto.Tests
{
- /// <summary>
- /// Standard vector test for SHA-512 from FIPS Draft 180-2.
- /// Note, the first two vectors are _not_ from the draft, the last three are.
- /// </summary>
- [TestFixture]
- public class Sha512DigestTest
- : ITest
- {
- public string Name
- {
- get { return "SHA512"; }
- }
-
- //private static string testVec1 = "";
- private static string resVec1 = "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e";
-
- private static string testVec2 = "61";
- private static string resVec2 = "1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75";
-
- private static string testVec3 = "616263";
- private static string resVec3 = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f";
-
- private static string testVec4 = "61626364656667686263646566676869636465666768696a6465666768696a6b65666768696a6b6c666768696a6b6c6d6768696a6b6c6d6e68696a6b6c6d6e6f696a6b6c6d6e6f706a6b6c6d6e6f70716b6c6d6e6f7071726c6d6e6f707172736d6e6f70717273746e6f707172737475";
- private static string resVec4 = "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909";
-
- // 1 million 'a'
- private static string testVec5 = "61616161616161616161";
- private static string resVec5 = "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b";
-
- public virtual ITestResult Perform()
- {
- IDigest digest = new Sha512Digest();
- byte[] resBuf = new byte[digest.GetDigestSize()];
- string resStr;
-
- //
- // test 1
- //
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec1.Equals(resStr))
- {
- return new SimpleTestResult(false, "SHA-512 failing standard vector test 1" + SimpleTest.NewLine + " expected: " + resVec1 + SimpleTest.NewLine + " got : " + resStr);
- }
-
- //
- // test 2
- //
- byte[] bytes = Hex.Decode(testVec2);
-
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec2.Equals(resStr))
- {
- return new SimpleTestResult(false, "SHA-512 failing standard vector test 2" + SimpleTest.NewLine + " expected: " + resVec2 + SimpleTest.NewLine + " got : " + resStr);
- }
-
- //
- // test 3
- //
- bytes = Hex.Decode(testVec3);
-
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec3.Equals(resStr))
- {
- return new SimpleTestResult(false, "SHA-512 failing standard vector test 3" + SimpleTest.NewLine + " expected: " + resVec3 + SimpleTest.NewLine + " got : " + resStr);
- }
-
- //
- // test 4
- //
- bytes = Hex.Decode(testVec4);
-
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec4.Equals(resStr))
- {
- return new SimpleTestResult(false, "SHA-512 failing standard vector test 4" + SimpleTest.NewLine + " expected: " + resVec4 + SimpleTest.NewLine + " got : " + resStr);
- }
-
- //
- // test 5
- //
- bytes = Hex.Decode(testVec4);
-
- digest.BlockUpdate(bytes, 0, bytes.Length / 2);
-
- // clone the IDigest
- IDigest d = new Sha512Digest((Sha512Digest)digest);
-
- digest.BlockUpdate(bytes, bytes.Length / 2, bytes.Length - bytes.Length / 2);
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec4.Equals(resStr))
- {
- return new SimpleTestResult(false, "SHA-512 failing standard vector test 5" + SimpleTest.NewLine + " expected: " + resVec4 + SimpleTest.NewLine + " got : " + resStr);
- }
-
- d.BlockUpdate(bytes, bytes.Length / 2, bytes.Length - bytes.Length / 2);
- d.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec4.Equals(resStr))
- {
- return new SimpleTestResult(false, "SHA-512 failing standard vector test 5" + SimpleTest.NewLine + " expected: " + resVec4 + SimpleTest.NewLine + " got : " + resStr);
- }
-
- // test 6
- bytes = Hex.Decode(testVec5);
- for (int i = 0; i < 100000; i++)
- {
- digest.BlockUpdate(bytes, 0, bytes.Length);
- }
- digest.DoFinal(resBuf, 0);
-
- resStr = Hex.ToHexString(resBuf);
- if (!resVec5.Equals(resStr))
- {
- return new SimpleTestResult(false, "SHA-512 failing standard vector test 6" + SimpleTest.NewLine + " expected: " + resVec5 + SimpleTest.NewLine + " got : " + resStr);
- }
-
- return new SimpleTestResult(true, Name + ": Okay");
- }
-
- public static void Main(
- string[] args)
- {
- ITest test = new Sha512DigestTest();
- ITestResult result = test.Perform();
-
- Console.WriteLine(result);
- }
+ /// <summary>
+ /// Standard vector test for SHA-512 from FIPS Draft 180-2.
+ /// Note, the first two vectors are _not_ from the draft, the last three are.
+ /// </summary>
+ [TestFixture]
+ public class Sha512DigestTest
+ : DigestTest
+ {
+ private static string[] messages =
+ {
+ "",
+ "a",
+ "abc",
+ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
+ };
+
+ private static string[] digests =
+ {
+ "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e",
+ "1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75",
+ "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f",
+ "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909"
+ };
+
+ // 1 million 'a'
+ static private string million_a_digest = "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b";
+
+ internal Sha512DigestTest()
+ : base(new Sha512Digest(), messages, digests)
+ {
+ }
+
+ public override void PerformTest()
+ {
+ base.PerformTest();
+
+ millionATest(million_a_digest);
+ }
+
+ protected override IDigest CloneDigest(IDigest digest)
+ {
+ return new Sha512Digest((Sha512Digest)digest);
+ }
+
+ public static void Main(
+ string[] args)
+ {
+ RunTest(new Sha512DigestTest());
+ }
[Test]
- public void TestFunction()
- {
- string resultText = Perform().ToString();
+ public void TestFunction()
+ {
+ string resultText = Perform().ToString();
Assert.AreEqual(Name + ": Okay", resultText);
- }
- }
+ }
+ }
}
diff --git a/crypto/test/src/crypto/test/SkeinDigestTest.cs b/crypto/test/src/crypto/test/SkeinDigestTest.cs
new file mode 100644
index 000000000..b6f1c542b
--- /dev/null
+++ b/crypto/test/src/crypto/test/SkeinDigestTest.cs
@@ -0,0 +1,303 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+
+ [TestFixture]
+ public class SkeinDigestTest
+ : SimpleTest
+ {
+ private class Case
+ {
+ private byte[] message;
+ private byte[] digest;
+ private int blockSize;
+ private int outputSize;
+
+ public Case(int blockSize, int outputSize, string message, string digest)
+ {
+ this.blockSize = blockSize;
+ this.outputSize = outputSize;
+ this.message = Hex.Decode(message);
+ this.digest = Hex.Decode(digest);
+ }
+
+ public int getOutputSize()
+ {
+ return outputSize;
+ }
+
+ public int getBlockSize()
+ {
+ return blockSize;
+ }
+
+ public byte[] getMessage()
+ {
+ return message;
+ }
+
+ public byte[] getDigest()
+ {
+ return digest;
+ }
+
+ }
+
+ // Test cases from skein_golden_kat.txt and skein_golden_kat_short.txt in Skein 1.3 NIST CD
+ private static readonly Case[] TEST_CASES = {
+ new Case(256, 256, "", "c8877087da56e072870daa843f176e9453115929094c3a40c463a196c29bf7ba"),
+ new Case(256, 256, "fb", "088eb23cc2bccfb8171aa64e966d4af937325167dfcd170700ffd21f8a4cbdac"),
+ new Case(256, 256, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8",
+ "5c3002ff57a627089ea2f97a5000d5678416389019e80e45a3bbcab118315d26"),
+ new Case(256, 256, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a129233",
+ "640c894a4bba6574c83e920ddf7dd2982fc634881bbbcb9d774eae0a285e89ce"),
+ new Case(256, 160, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "0cd491b7715704c3a15a45a1ca8d93f8f646d3a1"),
+ new Case(256, 224, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "afd1e2d0f5b6cd4e1f8b3935fa2497d27ee97e72060adac099543487"),
+ new Case(256, 256, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "4de6fe2bfdaa3717a4261030ef0e044ced9225d066354610842a24a3eafd1dcf"),
+ new Case(256, 384, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "954620fb31e8b782a2794c6542827026fe069d715df04261629fcbe81d7d529b"
+ + "95ba021fa4239fb00afaa75f5fd8e78b"),
+ new Case(256, 512, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "51347e27c7eabba514959f899a6715ef6ad5cf01c23170590e6a8af399470bf9"
+ + "0ea7409960a708c1dbaa90e86389df254abc763639bb8cdf7fb663b29d9557c3"),
+ new Case(256, 1024, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "6c9b6facbaf116b538aa655e0be0168084aa9f1be445f7e06714585e5999a6c9"
+ + "84fffa9d41a316028692d4aad18f573fbf27cf78e84de26da1928382b023987d"
+ + "cfe002b6201ea33713c54a8a5d9eb346f0365e04330d2faaf7bc8aba92a5d7fb"
+ + "6345c6fb26750bce65ab2045c233627679ac6e9acb33602e26fe3526063ecc8b"),
+
+ new Case(512, 512, "", "bc5b4c50925519c290cc634277ae3d6257212395cba733bbad37a4af0fa06af4"
+ + "1fca7903d06564fea7a2d3730dbdb80c1f85562dfcc070334ea4d1d9e72cba7a"),
+ new Case(512, 512, "fb", "c49e03d50b4b2cc46bd3b7ef7014c8a45b016399fd1714467b7596c86de98240"
+ + "e35bf7f9772b7d65465cd4cffab14e6bc154c54fc67b8bc340abf08eff572b9e"),
+ new Case(512, 512, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8",
+ "abefb179d52f68f86941acbbe014cc67ec66ad78b7ba9508eb1400ee2cbdb06f"
+ + "9fe7c2a260a0272d0d80e8ef5e8737c0c6a5f1c02ceb00fb2746f664b85fcef5"),
+ new Case(512, 512, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a129233",
+ "5c5b7956f9d973c0989aa40a71aa9c48a65af2757590e9a758343c7e23ea2df4"
+ + "057ce0b49f9514987feff97f648e1dd065926e2c371a0211ca977c213f14149f"),
+ new Case(512, 160, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "ef03079d61b57c6047e15fa2b35b46fa24279539"),
+ new Case(512, 224, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "d9e3219b214e15246a2038f76a573e018ef69b385b3bd0576b558231"),
+ new Case(512, 256, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "809dd3f763a11af90912bbb92bc0d94361cbadab10142992000c88b4ceb88648"),
+ new Case(512, 384, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "825f5cbd5da8807a7b4d3e7bd9cd089ca3a256bcc064cd73a9355bf3ae67f2bf"
+ + "93ac7074b3b19907a0665ba3a878b262"),
+ new Case(512, 512, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "1a0d5abf4432e7c612d658f8dcfa35b0d1ab68b8d6bd4dd115c23cc57b5c5bcd"
+ + "de9bff0ece4208596e499f211bc07594d0cb6f3c12b0e110174b2a9b4b2cb6a9"),
+
+ new Case(1024, 1024, "", "0fff9563bb3279289227ac77d319b6fff8d7e9f09da1247b72a0a265cd6d2a62"
+ + "645ad547ed8193db48cff847c06494a03f55666d3b47eb4c20456c9373c86297"
+ + "d630d5578ebd34cb40991578f9f52b18003efa35d3da6553ff35db91b81ab890"
+ + "bec1b189b7f52cb2a783ebb7d823d725b0b4a71f6824e88f68f982eefc6d19c6"),
+ new Case(1024, 1024, "fb", "6426bdc57b2771a6ef1b0dd39f8096a9a07554565743ac3de851d28258fcff22"
+ + "9993e11c4e6bebc8b6ecb0ad1b140276081aa390ec3875960336119427827473"
+ + "4770671b79f076771e2cfdaaf5adc9b10cbae43d8e6cd2b1c1f5d6c82dc96618"
+ + "00ddc476f25865b8748253173187d81da971c027d91d32fb390301c2110d2db2"),
+ new Case(1024, 1024, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8",
+ "140e93726ab0b0467c0b8a834ad8cda4d1769d273661902b70db0dcb5ee692ac"
+ + "b3f852d03b11f857850f2428432811309c1dcbe5724f00267ea3667e89fadb4e"
+ + "4911da6b0ba8a7eddf87c1c67152ef0f07b7fead3557318478bdef5ad1e5926d"
+ + "7071fdd4bfa5076d4b3253f8de479ebdf5357676f1641b2f097e9b785e9e528e"),
+ new Case(1024, 1024, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a129233",
+ "31105e1ef042c30b95b16e0f6e6a1a19172bb7d54a0597dd0c711194888efe1d"
+ + "bce82d47416df9577ca387219f06e45cd10964ff36f6711edbbea0e9595b0f66"
+ + "f72b755d70a46857e0aec98561a743d49370d8e572e212811273125f66cc30bf"
+ + "117d3221894c48012bf6e2219de91e064b01523517420a1e00f71c4cc04bab62"),
+ new Case(1024, 160, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "2e6a4cbf2ef05ea9c24b93e8d1de732ddf2739eb"),
+ new Case(1024, 224, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "1d6de19f37f7a3c265440eecb4b9fbd3300bb5ac60895cfc0d4d3c72"),
+ new Case(1024, 256, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "986a4d472b123e8148731a8eac9db23325f0058c4ccbc44a5bb6fe3a8db672d7"),
+ new Case(1024, 384, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "9c3d0648c11f31c18395d5e6c8ebd73f43d189843fc45235e2c35e345e12d62b"
+ + "c21a41f65896ddc6a04969654c2e2ce9"),
+ new Case(1024, 512, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "5d0416f49c2d08dfd40a1446169dc6a1d516e23b8b853be4933513051de8d5c2"
+ + "6baccffb08d3b16516ba3c6ccf3e9a6c78fff6ef955f2dbc56e1459a7cdba9a5"),
+ new Case(1024, 1024, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+ "96ca81f586c825d0360aef5acaec49ad55289e1797072eee198b64f349ce65b6"
+ + "e6ed804fe38f05135fe769cc56240ddda5098f620865ce4a4278c77fa2ec6bc3"
+ + "1c0f354ca78c7ca81665bfcc5dc54258c3b8310ed421d9157f36c093814d9b25"
+ + "103d83e0ddd89c52d0050e13a64c6140e6388431961685734b1f138fe2243086"),
+
+ };
+
+ public override string Name
+ {
+ get { return "SkeinDigest"; }
+ }
+
+ public override void PerformTest()
+ {
+ for (int i = 0; i < TEST_CASES.Length; i++)
+ {
+ Case test = TEST_CASES[i];
+ runTest(test);
+ }
+ }
+
+ private void runTest(Case dc)
+ {
+ SkeinDigest digest = new SkeinDigest(dc.getBlockSize(), dc.getOutputSize());
+
+ byte[] message = dc.getMessage();
+ digest.BlockUpdate(message, 0, message.Length);
+
+ byte[] output = new byte[digest.GetDigestSize()];
+ digest.DoFinal(output, 0);
+
+ if (!AreEqual(output, dc.getDigest()))
+ {
+ Fail(digest.AlgorithmName + " message mismatch.\n Message " + Hex.ToHexString(dc.getMessage()),
+ Hex.ToHexString(dc.getDigest()), Hex.ToHexString(output));
+ }
+
+ // Clone test
+ digest.BlockUpdate(message, 0, message.Length / 2);
+
+ // clone the Digest
+ IDigest d = new SkeinDigest(digest);
+
+ digest.BlockUpdate(message, message.Length / 2, message.Length - message.Length / 2);
+ digest.DoFinal(output, 0);
+
+ if (!AreEqual(dc.getDigest(), output))
+ {
+ Fail("failing clone vector test", Hex.ToHexString(dc.getDigest()), Hex.ToHexString(output));
+ }
+
+ d.BlockUpdate(message, message.Length / 2, message.Length - message.Length / 2);
+ d.DoFinal(output, 0);
+
+ if (!AreEqual(dc.getDigest(), output))
+ {
+ Fail("failing second clone vector test", Hex.ToHexString(dc.getDigest()), Hex.ToHexString(output));
+ }
+
+ // //
+ // // memo test
+ // //
+ // Memoable m = (Memoable)digest;
+ //
+ // digest.Update(message, 0, message.Length / 2);
+ //
+ // // copy the Digest
+ // Memoable copy1 = m.copy();
+ // Memoable copy2 = copy1.copy();
+ //
+ // digest.Update(message, message.Length / 2, message.Length - message.Length / 2);
+ // digest.DoFinal(output, 0);
+ //
+ // if (!AreEqual(dc.getDigest(), output))
+ // {
+ // Fail("failing memo vector test", Hex.ToHexString(dc.getDigest()), Hex.ToHexString(output));
+ // }
+ //
+ // m.reset(copy1);
+ //
+ // digest.Update(message, message.Length / 2, message.Length - message.Length / 2);
+ // digest.DoFinal(output, 0);
+ //
+ // if (!AreEqual(dc.getDigest(), output))
+ // {
+ // fail("failing memo reset vector test", Hex.ToHexString(dc.getDigest()), Hex.ToHexString(output));
+ // }
+ //
+ // IDigest md = (IDigest)copy2;
+ //
+ // md.Update(message, message.Length / 2, message.Length - message.Length / 2);
+ // md.DoFinal(output, 0);
+ //
+ // if (!AreEqual(dc.getDigest(), output))
+ // {
+ // Fail("failing memo copy vector test", Hex.ToHexString(dc.getDigest()), Hex.ToHexString(output));
+ // }
+ }
+
+ public static void Main(
+ string[] args)
+ {
+ RunTest(new SkeinDigestTest());
+ }
+
+ [Test]
+ public void TestFunction()
+ {
+ string resultText = Perform().ToString();
+
+ Assert.AreEqual(Name + ": Okay", resultText);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/crypto/test/src/crypto/test/SkeinMacTest.cs b/crypto/test/src/crypto/test/SkeinMacTest.cs
new file mode 100644
index 000000000..852c3b2c7
--- /dev/null
+++ b/crypto/test/src/crypto/test/SkeinMacTest.cs
@@ -0,0 +1,174 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+
+ [TestFixture]
+ public class SkeinMacTest
+ : SimpleTest
+ {
+ private class Case
+ {
+ private byte[] message;
+ private byte[] digest;
+ private byte[] key;
+ private int blockSize;
+ private int outputSize;
+
+ public Case(int blockSize, int outputSize, String message, String key, String digest)
+ {
+ this.blockSize = blockSize;
+ this.outputSize = outputSize;
+ this.message = Hex.Decode(message);
+ this.key = Hex.Decode(key);
+ this.digest = Hex.Decode(digest);
+ }
+
+ public int getOutputSize()
+ {
+ return outputSize;
+ }
+
+ public int getBlockSize()
+ {
+ return blockSize;
+ }
+
+ public byte[] getMessage()
+ {
+ return message;
+ }
+
+ public byte[] getKey()
+ {
+ return key;
+ }
+
+ public byte[] getDigest()
+ {
+ return digest;
+ }
+
+ public override string ToString()
+ {
+ return String.Format("new Case({0}, {1}, \"{2}\", \"{3}\", \"{4}\"),", blockSize, outputSize,
+ Hex.ToHexString(message), Hex.ToHexString(key), Hex.ToHexString(digest));
+ }
+
+ }
+
+ // Test cases from skein_golden_kat.txt in Skein 1.3 NIST CD
+ // Excludes empty '(none)' key 'random+MAC' tests, which are in effect digest
+ private static readonly Case[] TEST_CASES = {
+ new Case(256, 256, "", "cb41f1706cde09651203c2d0efbaddf8", "886e4efefc15f06aa298963971d7a25398fffe5681c84db39bd00851f64ae29d"),
+ new Case(256, 256, "d3", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "979422a94e3afaa46664124d4e5e8b9422b1d8baf11c6ae6725992ac72a112ca"),
+ new Case(256, 256, "d3090c72", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "1d658372cbea2f9928493cc47599d6f4ad8ce33536bedfa20b739f07516519d5"),
+ new Case(256, 256, "d3090c72167517f7", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e92", "41ef6b0f0fad81c040284f3b1a91e9c44e4c26a6d7207f3aac4362856ef12aca"),
+ new Case(256, 256, "d3090c72167517f7c7ad82a70c2fd3f6", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "ca8208119b9e4e4057631ab31015cfd256f6763a0a34381633d97f640899b84f"),
+ new Case(256, 256, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "9e9980fcc16ee082cf164a5147d0e0692aeffe3dcb8d620e2bb542091162e2e9"),
+ new Case(256, 256, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc235", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "c353a316558ec34f8245dd2f9c2c4961fbc7decc3b69053c103e4b8aaaf20394"),
+ new Case(256, 256, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdf", "cb41f1706cde09651203c2d0efbaddf8", "b1b8c18188e69a6ecae0b6018e6b638c6a91e6de6881e32a60858468c17b520d"),
+ new Case(256, 256, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e92", "1dfd2515a412e78852cd81a7f2167711b4ca19b2891c2ea36ba94f8451944793"),
+ new Case(256, 224, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf8", "a097340709b443ed2c0a921f5dcefef3ead65c4f0bcd5f13da54d7ed"),
+ new Case(256, 256, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "ac1b4fab6561c92d0c487e082daec53e0db4f505e08bf51cae4fd5375e37fc04"),
+ new Case(256, 384, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e92", "96e6cebb23573d0a70ce36a67aa05d2403148093f25c695e1254887cc97f9771d2518413af4286bf2a06b61a53f7fcec"),
+ new Case(256, 512, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "0e95e597e71d6350f20b99c4179f54f43a4722705c06ba765a82cb0a314fe2fe87ef8090063b757e53182706ed18737dadc0da1e1c66518f08334052702c5ed7"),
+ new Case(256, 264, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf8", "064abd4896f460b1953f5a357e7f7c5256e29cdb62b8740d0b52295cfa2ef4c7a2"),
+ new Case(256, 520, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "edf220e43e048603bd16197d59b673b9974de5b8bcf7cb1558a4799f6fd3743eb5fb400cd6129afc0c60e7b741b7e5806f0e0b93eb8429fbc7efa222175a9c80fd"),
+ new Case(256, 1032, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e92", "f3f59fb07399c7b73aae02a8590883cb2fdfde75c55654e71846522301bde48d267169adcc559e038e8c2f28faa552b550d51874055384adea93c036c71a1f0af0c7bcc3bc923738d5307b9da7cb423d4e615c629c4aba71f70d4c9d1fa008176825e51bfa0203445a4083947ec19f6a0fbd082b5b970f2396fb67420639410447"),
+ new Case(256, 2056, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "80eb80d9b8836b32fa576fc84ba08edfbdfd6979123d61914e610a70a372b37f560a10909484f9f4a377c93e29ba681dfe522c41dc83b5ee0567e5370007c7bbe4df0b2b4a25e088f80d72fc30734cdcd76d817b42fbd44dca881019afb25306f19d4e91848778af306517d2072cef72caa327e877c5b6554f83cec3d00877131b47c4d3b557f5a13541c4d5080ee3ce7a658993d083efd0db3496a8752060c3c8552f44b290cabdcc867f691ad605836c08dbd59c9528d885b600b85fdfc8a9d0e636ac3ad8b4295bcb0169e78dc358e77eacc8c4b61bddfa9e5f32d2268a006cfe05c57150fe8e68cabd21cf6cf6035aa1fe4db36c922b765aad0b64e82a2c37"),
+ new Case(256, 256, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed696e6c9db1e6abea026288954a9c2d5758d7c5db7c9e48aa3d21cae3d977a7c3926066aa393dbd538dd0c30da8916c8757f24c18488014668a2627163a37b261833dc2f8c3c56b1b2e0be21fd3fbdb507b2950b77a6cc02efb393e57419383a920767bca2c972107aa61384542d47cbfb82cfe5c415389d1b0a2d74e2c5da851", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "8f88de68f03cd2f396ccdd49c3a0f4ff15bcda7eb357da9753f6116b124de91d"),
+ new Case(512, 512, "", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "9bd43d2a2fcfa92becb9f69faab3936978f1b865b7e44338fc9c8f16aba949ba340291082834a1fc5aa81649e13d50cd98641a1d0883062bfe2c16d1faa7e3aa"),
+ new Case(512, 512, "d3", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "f0c0a10f031c8fc69cfabcd54154c318b5d6cd95d06b12cf20264402492211ee010d5cecc2dc37fd772afac0596b2bf71e6020ef2dee7c860628b6e643ed9ff6"),
+ new Case(512, 512, "d3090c72167517f7", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "0c1f1921253dd8e5c2d4c5f4099f851042d91147892705829161f5fc64d89785226eb6e187068493ee4c78a4b7c0f55a8cbbb1a5982c2daf638fc6a74b16b0d7"),
+ new Case(512, 512, "d3090c72167517f7c7ad82a70c2fd3f6", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "478d7b6c0cc6e35d9ebbdedf39128e5a36585db6222891692d1747d401de34ce3db6fcbab6c968b7f2620f4a844a2903b547775579993736d2493a75ff6752a1"),
+ new Case(512, 512, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e59", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "13c170bac1de35e5fb843f65fabecf214a54a6e0458a4ff6ea5df91915468f4efcd371effa8965a9e82c5388d84730490dcf3976af157b8baf550655a5a6ab78"),
+ new Case(512, 512, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc235", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "a947812529a72fd3b8967ec391b298bee891babc8487a1ec4ea3d88f6b2b5be09ac6a780f30f8e8c3bbb4f18bc302a28f3e87d170ba0f858a8fefe3487478cca"),
+ new Case(512, 512, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdf", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "7690ba61f10e0bba312980b0212e6a9a51b0e9aadfde7ca535754a706e042335b29172aae29d8bad18efaf92d43e6406f3098e253f41f2931eda5911dc740352"),
+ new Case(512, 512, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "d10e3ba81855ac087fbf5a3bc1f99b27d05f98ba22441138026225d34a418b93fd9e8dfaf5120757451adabe050d0eb59d271b0fe1bbf04badbcf9ba25a8791b"),
+ new Case(512, 160, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "5670b226156570dff3efe16661ab86eb24982cdf"),
+ new Case(512, 224, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "c41b9ff9753e6c0f8ed88866e320535e927fe4da552c289841a920db"),
+ new Case(512, 384, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "dfbf5c1319a1d9d70efb2f1600fbcf694f935907f31d24a16d6cd2fb2d7855a769681766c0a29da778eed346cd1d740f"),
+ new Case(512, 512, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "04d8cddb0ad931d54d195899a094684344e902286037272890bce98a41813edc37a3cee190a693fcca613ee30049ce7ec2bdff9613f56778a13f8c28a21d167a"),
+ new Case(512, 1024, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "08fca368b3b14ac406676adf37ac9be2dbb8704e694055a0c6331184d4f0070098f23f0963ee29002495771bf56fb4d3d9ff3506abcd80be927379f7880d5d7703919fbf92184f498ac44f47f015ce676eded9165d47d53733f5a27abbc05f45acd98b97cc15ffdced641defd1a5119ef841b452a1b8f94ee69004466ccdc143"),
+ new Case(512, 264, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "669e770ebe7eacc2b64caaf049923ad297a5b37cfa61c283392d81ccfcb9bbbc09"),
+ new Case(512, 1032, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "acc2e03f07f33e9820a6038421089429adcd6a7a83f733beec048c05bf37531a170a5537fcb565c348a70a83217f8be768ff6f95fd2b3d89cb7d8a3dc849505e3710eb4e65a8e7134bbf580d92fe18c9aa987563669b1f014aa5e092519089355534eaa9f0bdc99f6839f54080ffe74623254c906ecb8896b4346c3178a0bc2898"),
+ new Case(512, 2056, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "9f3e082223c43090a4a3ffbdcd469cbabfe0c1399d1edf45a5dfc18f4db5428928a76e979b8d0d5dffec0e6a59ada448c1ffbc06cc80a2006f002adc0c6dbf458563762228dce4381944e460ebebfe06f1237093634625107469a22a189a47f8b025899265d8890a1b39df64552394377e88ba2ad44a8c8d174f884ac8c3ae24ddb0affca5fceb6aa76e09706881e8371774b9b050a69b96ef5e97e81043f8b7e9479e287ab441bacd62caf768a82c8c3e3107be70eb8799a39856fe29842a04e25de0ef9de1b7e65bd0f1f7306835287fc957388e2035b7d22d3aa9c06a9fefbca16f3f60e1c4def89038d918942152a069aa2e0be8ae7475d859031adec84583"),
+ new Case(1024, 1024, "", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc81463134", "bcf37b3459c88959d6b6b58b2bfe142cef60c6f4ec56b0702480d7893a2b0595aa354e87102a788b61996b9cbc1eade7dafbf6581135572c09666d844c90f066b800fc4f5fd1737644894ef7d588afc5c38f5d920bdbd3b738aea3a3267d161ed65284d1f57da73b68817e17e381ca169115152b869c66b812bb9a84275303f0"),
+ new Case(1024, 1024, "d3090c72", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "df0596e5808835a3e304aa27923db05f61dac57c0696a1d19abf188e70aa9dbcc659e9510f7c9a37fbc025bd4e5ea293e78ed7838dd0b08864e8ad40ddb3a88031ebefc21572a89960d1916107a7da7ac0c067e34ec46a86a29ca63fa250bd398eb32ec1ed0f8ac8329f26da018b029e41e2e58d1dfc44de81615e6c987ed9c9"),
+ new Case(1024, 1024, "d3090c72167517f7", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c042eb4187aa1c015a4767032c0bb28f076b66485f51531c12e948f47dbc2cb904a4b75d1e8a6d931dab4a07e0a54d1bb5b55e602141746bd09fb15e8f01a8d74e9e63959cb37336bc1b896ec78da734c15e362db04368fbba280f20a043e0d0941e9f5193e1b360a33c43b266524880125222e648f05f28be34ba3cabfc9c544", "3cfbb79cd88af8ee09c7670bcbab6907a31f80fa31d9d7c9d50826c9568f307a78bd254961398c76b6e338fd9ca5f351059350d30963c3320659b223b991fc46d1307686fe2b4763d9f593c57ad5adbc45caf2ea3dc6090f5a74fa5fa6d9e9838964ea0a2aa216831ab069b00629a1a9b037083403bdb25d3d06a21c430c87dd"),
+ new Case(1024, 1024, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e59", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "0a1b960099fc9d653b0fd1f5b6b972fb366907b772cbce5a59b6171d7935506f70c212bd169d68c5cfd8618343611b7eb2e686ff1dc7c03a57e1a55ed10726848161eea903d53b58459be42d95df989c66c2eea4e51cde272c2d8be67bf3bca2aee633777eb8486781eaa060d0f538abd6c93dbd2d1bf66e6f50bfdcac3725a4"),
+ new Case(1024, 1024, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "3e0cd7938d71c39ffbb08a6ba7995ade3ad140e2c0c45cdbafb099247e08e4c20b61c1f885ced5ed2f816680925034918236e5807f0eecf3f27e9cfca36675eb75873efa1fb41f17541dc2f7c2469eaecb35cc7ca58e489804caf56f09fb97c9f689c64ad49c6888f86c483e901bd3d25798b394ef93faf9154900f92f31f433"),
+ new Case(1024, 1024, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdf", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc81463134", "7266752f7e9aa04bd7d8a1b16030677de6021301f6a62473c76bae2b98bbf8aad73bd00a4b5035f741caf2317ab80e4e97f5c5bbe8acc0e8b424bcb13c7c6740a985801fba54addde8d4f13f69d2bfc98ae104d46a211145217e51d510ea846cec9581d14fda079f775c8b18d66cb31bf7060996ee8a69eee7f107909ce59a97"),
+ new Case(1024, 1024, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c042eb4187aa1c015a4767032c0bb28f076b66485f51531c12e948f47dbc2cb904a4b75d1e8a6d931dab4a07e0a54d1bb5b55e602141746bd09fb15e8f01a8d74e9e63959cb37336bc1b896ec78da734c15e362db04368fbba280f20a043e0d0941e9f5193e1b360a33c43b266524880125222e648f05f28be34ba3cabfc9c544", "71f40bf2aa635125ef83c8df0d4e9ea18b73b56be4f45e89b910a7c68d396b65b09d18abc7d1b6de3f53fd5de583e6f22e612dd17b292068af6027daaf8b4cd60acf5bc85044741e9f7a1f423f5827f5e360930a2e71912239af9fc6343604fdcf3f3569854f2bb8d25a81e3b3f5261a02fe8292aaaa50c324101ab2c7a2f349"),
+ new Case(1024, 160, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "17c3c533b27d666da556ae586e641b7a3a0bcc45"),
+ new Case(1024, 224, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc81463134", "6625df9801581009125ea4e5c94ad6f1a2d692c278822ccb6eb67235"),
+ new Case(1024, 256, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "6c5b671c1766f6eecea6d24b641d4a6bf84bba13a1976f8f80b3f30ee2f93de6"),
+ new Case(1024, 384, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c042eb4187aa1c015a4767032c0bb28f076b66485f51531c12e948f47dbc2cb904a4b75d1e8a6d931dab4a07e0a54d1bb5b55e602141746bd09fb15e8f01a8d74e9e63959cb37336bc1b896ec78da734c15e362db04368fbba280f20a043e0d0941e9f5193e1b360a33c43b266524880125222e648f05f28be34ba3cabfc9c544", "98af454d7fa3706dfaafbf58c3f9944868b57f68f493987347a69fce19865febba0407a16b4e82065035651f0b1e0327"),
+ new Case(1024, 1024, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "211ac479e9961141da3aac19d320a1dbbbfad55d2dce87e6a345fcd58e36827597378432b482d89bad44dddb13e6ad86e0ee1e0882b4eb0cd6a181e9685e18dd302ebb3aa74502c06254dcadfb2bd45d288f82366b7afc3bc0f6b1a3c2e8f84d37fbedd07a3f8fcff84faf24c53c11da600aaa118e76cfdcb366d0b3f7729dce"),
+ new Case(1024, 264, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc81463134", "dc1d253b7cadbdaef18503b1809a7f1d4f8c323b7f6f8ca50b76d3864649ce1c7d"),
+ new Case(1024, 520, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "decd79578d12bf6806530c382230a2c7836429c70cac941179e1dd982938bab91fb6f3638df1cc1ef615ecfc4249e5aca8a73c4c1eebef662a836d0be903b00146"),
+ new Case(1024, 1032, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c042eb4187aa1c015a4767032c0bb28f076b66485f51531c12e948f47dbc2cb904a4b75d1e8a6d931dab4a07e0a54d1bb5b55e602141746bd09fb15e8f01a8d74e9e63959cb37336bc1b896ec78da734c15e362db04368fbba280f20a043e0d0941e9f5193e1b360a33c43b266524880125222e648f05f28be34ba3cabfc9c544", "440fe691e04f1fed8c253d6c4670646156f33fffaea702de9445df5739eb960cecf85d56e2e6860a610211a5c909932ab774b978aa0b0d5bbce82775172ab12dceddd51d1eb030057ce61bea6c18f6bb368d26ae76a9e44a962eb132e6c42c25d9fecc4f13348300ca55c78e0990de96c1ae24eb3ee3324782c93dd628260a2c8d"),
+ new Case(1024, 1024, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed696e6c9db1e6abea026288954a9c2d5758d7c5db7c9e48aa3d21cae3d977a7c3926066aa393dbd538dd0c30da8916c8757f24c18488014668a2627163a37b261833dc2f8c3c56b1b2e0be21fd3fbdb507b2950b77a6cc02efb393e57419383a920767bca2c972107aa61384542d47cbfb82cfe5c415389d1b0a2d74e2c5da851", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "46a42b0d7b8679f8fcea156c072cf9833c468a7d59ac5e5d326957d60dfe1cdfb27eb54c760b9e049fda47f0b847ac68d6b340c02c39d4a18c1bdfece3f405fae8aa848bdbefe3a4c277a095e921228618d3be8bd1999a071682810de748440ad416a97742cc9e8a9b85455b1d76472cf562f525116698d5cd0a35ddf86e7f8a"),
+
+ };
+
+ public override string Name
+ {
+ get { return "SkeinMac"; }
+ }
+
+ public override void PerformTest()
+ {
+ for (int i = 0; i < TEST_CASES.Length; i++)
+ {
+ Case test = TEST_CASES[i];
+ runTest(test);
+ }
+ }
+
+ private void runTest(Case dc)
+ {
+ IMac digest = new SkeinMac(dc.getBlockSize(), dc.getOutputSize());
+ digest.Init(new KeyParameter(dc.getKey()));
+
+ byte[] message = dc.getMessage();
+ digest.BlockUpdate(message, 0, message.Length);
+
+ byte[] output = new byte[digest.GetMacSize()];
+ digest.DoFinal(output, 0);
+
+ if (!AreEqual(output, dc.getDigest()))
+ {
+ Fail(digest.AlgorithmName + " message " + (dc.getMessage().Length * 8) + " mismatch.\n Message " + Hex.ToHexString(dc.getMessage())
+ + "\n Key " + Hex.ToHexString(dc.getKey()) + "\n Expected "
+ + Hex.ToHexString(dc.getDigest()) + "\n Actual " + Hex.ToHexString(output));
+ }
+
+ }
+
+ public static void Main(
+ string[] args)
+ {
+ RunTest(new SkeinMacTest());
+ }
+
+ [Test]
+ public void TestFunction()
+ {
+ string resultText = Perform().ToString();
+
+ Assert.AreEqual(Name + ": Okay", resultText);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/crypto/test/src/crypto/test/Sm3DigestTest.cs b/crypto/test/src/crypto/test/Sm3DigestTest.cs
new file mode 100644
index 000000000..3d004deaa
--- /dev/null
+++ b/crypto/test/src/crypto/test/Sm3DigestTest.cs
@@ -0,0 +1,74 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+ /**
+ * standard vector test for SM3 digest from chinese specification
+ */
+ [TestFixture]
+ public class Sm3DigestTest
+ : DigestTest
+ {
+ private static string[] messages = {
+ // Standard test vectors
+ "abc",
+ "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd",
+ // Non-standard test vectors
+ "",
+ "a",
+ "abcdefghijklmnopqrstuvwxyz",
+ };
+
+ private static string[] digests = {
+ // Standard test vectors
+ "66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0",
+ "debe9ff92275b8a138604889c18e5a4d6fdb70e5387e5765293dcba39c0c5732",
+ // Non-standard test vectors
+ "1ab21d8355cfa17f8e61194831e81a8f22bec8c728fefb747ed035eb5082aa2b",
+ "623476ac18f65a2909e43c7fec61b49c7e764a91a18ccb82f1917a29c86c5e88",
+ "b80fe97a4da24afc277564f66a359ef440462ad28dcc6d63adb24d5c20a61595",
+ };
+
+ private static string sixtyFourKdigest = "97049bdc8f0736bc7300eafa9980aeb9cf00f24f7ec3a8f1f8884954d7655c1d";
+ private static string million_a_digest = "c8aaf89429554029e231941a2acc0ad61ff2a5acd8fadd25847a3a732b3b02c3";
+
+ internal Sm3DigestTest()
+ : base(new Sm3Digest(), messages, digests)
+ {
+ }
+
+ public override void PerformTest()
+ {
+ base.PerformTest();
+
+ sixtyFourKTest(sixtyFourKdigest);
+ millionATest(million_a_digest);
+ }
+
+ protected override IDigest CloneDigest(IDigest digest)
+ {
+ return new Sm3Digest((Sm3Digest)digest);
+ }
+
+ public static void Main(
+ string[] args)
+ {
+ RunTest(new Sm3DigestTest());
+ }
+
+ [Test]
+ public void TestFunction()
+ {
+ string resultText = Perform().ToString();
+
+ Assert.AreEqual(Name + ": Okay", resultText);
+ }
+ }
+}
diff --git a/crypto/test/src/crypto/test/Threefish1024Test.cs b/crypto/test/src/crypto/test/Threefish1024Test.cs
new file mode 100644
index 000000000..64f9aa29f
--- /dev/null
+++ b/crypto/test/src/crypto/test/Threefish1024Test.cs
@@ -0,0 +1,74 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+
+ [TestFixture]
+ public class Threefish1024Test
+ : CipherTest
+ {
+ // Test cases from skein_golden_kat_internals.txt in Skein 1.3 NIST CD
+ static SimpleTest[] tests =
+ {
+ new BlockCipherVectorTest(0, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_1024),
+ new TweakableBlockCipherParameters(
+ new KeyParameter(new byte[128]),
+ new byte[16]),
+ "0000000000000000000000000000000000000000000000000000000000000000" +
+ "0000000000000000000000000000000000000000000000000000000000000000" +
+ "0000000000000000000000000000000000000000000000000000000000000000" +
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "f05c3d0a3d05b304f785ddc7d1e036015c8aa76e2f217b06c6e1544c0bc1a90d" +
+ "f0accb9473c24e0fd54fea68057f43329cb454761d6df5cf7b2e9b3614fbd5a2" +
+ "0b2e4760b40603540d82eabc5482c171c832afbe68406bc39500367a592943fa" +
+ "9a5b4a43286ca3c4cf46104b443143d560a4b230488311df4feef7e1dfe8391e"),
+ new BlockCipherVectorTest(1, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_1024),
+ new TweakableBlockCipherParameters(
+ new KeyParameter(Hex.Decode(
+ "101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f" +
+ "303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f" +
+ "505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f" +
+ "707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f")),
+ Hex.Decode("000102030405060708090a0b0c0d0e0f")),
+ "fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0" +
+ "dfdedddcdbdad9d8d7d6d5d4d3d2d1d0cfcecdcccbcac9c8c7c6c5c4c3c2c1c0" +
+ "bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0afaeadacabaaa9a8a7a6a5a4a3a2a1a0" +
+ "9f9e9d9c9b9a999897969594939291908f8e8d8c8b8a89888786858483828180",
+ "a6654ddbd73cc3b05dd777105aa849bce49372eaaffc5568d254771bab85531c" +
+ "94f780e7ffaae430d5d8af8c70eebbe1760f3b42b737a89cb363490d670314bd" +
+ "8aa41ee63c2e1f45fbd477922f8360b388d6125ea6c7af0ad7056d01796e90c8" +
+ "3313f4150a5716b30ed5f569288ae974ce2b4347926fce57de44512177dd7cde")
+ };
+
+ public Threefish1024Test()
+ : base(tests, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_1024), new KeyParameter(new byte[128]))
+ {
+ }
+
+ public override string Name
+ {
+ get { return "Threefish-1024"; }
+ }
+
+ public static void Main(
+ string[] args)
+ {
+ RunTest(new Threefish1024Test());
+ }
+
+ [Test]
+ public void TestFunction()
+ {
+ string resultText = Perform().ToString();
+
+ Assert.AreEqual(Name + ": Okay", resultText);
+ }
+ }
+}
diff --git a/crypto/test/src/crypto/test/Threefish256Test.cs b/crypto/test/src/crypto/test/Threefish256Test.cs
new file mode 100644
index 000000000..e44299a31
--- /dev/null
+++ b/crypto/test/src/crypto/test/Threefish256Test.cs
@@ -0,0 +1,59 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+
+ [TestFixture]
+ public class Threefish256Test
+ : CipherTest
+ {
+ // Test cases from skein_golden_kat_internals.txt in Skein 1.3 NIST CD
+ static SimpleTest[] tests =
+ {
+ new BlockCipherVectorTest(0, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_256),
+ new TweakableBlockCipherParameters(
+ new KeyParameter(new byte[32]),
+ new byte[16]),
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "84da2a1f8beaee947066ae3e3103f1ad536db1f4a1192495116b9f3ce6133fd8"),
+ new BlockCipherVectorTest(1, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_256),
+ new TweakableBlockCipherParameters(
+ new KeyParameter(Hex.Decode(
+ "101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f")),
+ Hex.Decode("000102030405060708090a0b0c0d0e0f")),
+ "FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0",
+ "e0d091ff0eea8fdfc98192e62ed80ad59d865d08588df476657056b5955e97df")
+ };
+
+ public Threefish256Test()
+ : base(tests, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_256), new KeyParameter(new byte[32]))
+ {
+ }
+
+ public override string Name
+ {
+ get { return "Threefish-256"; }
+ }
+
+ public static void Main(
+ string[] args)
+ {
+ RunTest(new Threefish256Test());
+ }
+
+ [Test]
+ public void TestFunction()
+ {
+ string resultText = Perform().ToString();
+
+ Assert.AreEqual(Name + ": Okay", resultText);
+ }
+ }
+}
\ No newline at end of file
diff --git a/crypto/test/src/crypto/test/Threefish512Test.cs b/crypto/test/src/crypto/test/Threefish512Test.cs
new file mode 100644
index 000000000..8f4ec6345
--- /dev/null
+++ b/crypto/test/src/crypto/test/Threefish512Test.cs
@@ -0,0 +1,64 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+
+ [TestFixture]
+ public class Threefish512Test
+ : CipherTest
+ {
+ // Test cases from skein_golden_kat_internals.txt in Skein 1.3 NIST CD
+ static SimpleTest[] tests =
+ {
+ new BlockCipherVectorTest(0, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_512),
+ new TweakableBlockCipherParameters(
+ new KeyParameter(new byte[64]),
+ new byte[16]),
+ "0000000000000000000000000000000000000000000000000000000000000000" +
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "b1a2bbc6ef6025bc40eb3822161f36e375d1bb0aee3186fbd19e47c5d479947b" +
+ "7bc2f8586e35f0cff7e7f03084b0b7b1f1ab3961a580a3e97eb41ea14a6d7bbe"),
+ new BlockCipherVectorTest(1, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_512),
+ new TweakableBlockCipherParameters(
+ new KeyParameter(Hex.Decode(
+ "101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f" +
+ "303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f")),
+ Hex.Decode("000102030405060708090a0b0c0d0e0f")),
+ "fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0" +
+ "dfdedddcdbdad9d8d7d6d5d4d3d2d1d0cfcecdcccbcac9c8c7c6c5c4c3c2c1c0",
+ "e304439626d45a2cb401cad8d636249a6338330eb06d45dd8b36b90e97254779" +
+ "272a0a8d99463504784420ea18c9a725af11dffea10162348927673d5c1caf3d")
+ };
+
+ public Threefish512Test()
+ : base(tests, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_512), new KeyParameter(new byte[64]))
+ {
+ }
+
+ public override string Name
+ {
+ get { return "Threefish-512"; }
+ }
+
+ public static void Main(
+ string[] args)
+ {
+ RunTest(new Threefish512Test());
+ }
+
+ [Test]
+ public void TestFunction()
+ {
+ string resultText = Perform().ToString();
+
+ Assert.AreEqual(Name + ": Okay", resultText);
+ }
+ }
+}
\ No newline at end of file
diff --git a/crypto/test/src/crypto/test/TigerDigestTest.cs b/crypto/test/src/crypto/test/TigerDigestTest.cs
index 6fec60185..21bcfe78d 100644
--- a/crypto/test/src/crypto/test/TigerDigestTest.cs
+++ b/crypto/test/src/crypto/test/TigerDigestTest.cs
@@ -20,7 +20,7 @@ namespace Org.BouncyCastle.Crypto.Tests
*/
[TestFixture]
public class TigerDigestTest
- : ITest
+ : DigestTest
{
readonly static string[] messages =
{
@@ -48,93 +48,35 @@ namespace Org.BouncyCastle.Crypto.Tests
readonly static string hash64k = "FDF4F5B35139F48E710E421BE5AF411DE1A8AAC333F26204";
- public string Name
- {
- get { return "Tiger"; }
- }
-
- public ITestResult Perform()
- {
- IDigest digest = new TigerDigest();
- byte[] resBuf = new byte[digest.GetDigestSize()];
-
- for (int i = 0; i < messages.Length; i++)
- {
- byte[] m = Encoding.ASCII.GetBytes(messages[i]);
- digest.BlockUpdate(m, 0, m.Length);
- digest.DoFinal(resBuf, 0);
-
- if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[i])))
- {
- return new SimpleTestResult(false, Name + ": Vector " + i + " failed got " + Hex.ToHexString(resBuf));
- }
- }
-
- //
- // test 2
- //
- byte[] mm = Encoding.ASCII.GetBytes(messages[messages.Length-1]);
-
- digest.BlockUpdate(mm, 0, mm.Length/2);
-
- // clone the IDigest
- IDigest d = new TigerDigest((TigerDigest)digest);
+ internal TigerDigestTest()
+ : base(new TigerDigest(), messages, digests)
+ {
+ }
- digest.BlockUpdate(mm, mm.Length/2, mm.Length - mm.Length/2);
- digest.DoFinal(resBuf, 0);
+ public override void PerformTest()
+ {
+ base.PerformTest();
- if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[digests.Length-1])))
- {
- return new SimpleTestResult(false,
- "Tiger failing clone test"
- + SimpleTest.NewLine
- + " expected: " + digests[digests.Length-1]
- + SimpleTest.NewLine
- + " got : " + Hex.ToHexString(resBuf));
- }
+ sixtyFourKTest(hash64k);
+ }
- d.BlockUpdate(mm, mm.Length/2, mm.Length - mm.Length/2);
- d.DoFinal(resBuf, 0);
+ protected override IDigest CloneDigest(IDigest digest)
+ {
+ return new TigerDigest((TigerDigest)digest);
+ }
- if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[digests.Length-1])))
- {
- return new SimpleTestResult(false,
- "Tiger failing clone test - part 2"
- + SimpleTest.NewLine
- + " expected: " + digests[digests.Length-1]
- + SimpleTest.NewLine
- + " got : " + Hex.ToHexString(resBuf));
- }
-
- for (int i = 0; i < 65536; i++)
- {
- digest.Update((byte)(i & 0xff));
- }
- digest.DoFinal(resBuf, 0);
-
- if (!Arrays.AreEqual(resBuf, Hex.Decode(hash64k)))
- {
- return new SimpleTestResult(false, Name + ": Million a's failed");
- }
-
- return new SimpleTestResult(true, Name + ": Okay");
- }
-
- public static void Main(
- string[] args)
- {
- ITest test = new TigerDigestTest();
- ITestResult result = test.Perform();
-
- Console.WriteLine(result);
- }
+ public static void Main(
+ string[] args)
+ {
+ RunTest(new TigerDigestTest());
+ }
[Test]
- public void TestFunction()
- {
- string resultText = Perform().ToString();
+ public void TestFunction()
+ {
+ string resultText = Perform().ToString();
- Assert.AreEqual(Name + ": Okay", resultText);
- }
+ Assert.AreEqual(Name + ": Okay", resultText);
+ }
}
}
diff --git a/crypto/test/src/crypto/test/WhirlpoolDigestTest.cs b/crypto/test/src/crypto/test/WhirlpoolDigestTest.cs
index 865408f6a..eff9b1c2e 100644
--- a/crypto/test/src/crypto/test/WhirlpoolDigestTest.cs
+++ b/crypto/test/src/crypto/test/WhirlpoolDigestTest.cs
@@ -5,135 +5,107 @@ using NUnit.Framework;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Encodings;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.Utilities.Test;
namespace Org.BouncyCastle.Crypto.Tests
{
+
/**
* ISO vector test for Whirlpool
- *
+ *
*/
[TestFixture]
public class WhirlpoolDigestTest
- : SimpleTest
+ : DigestTest
{
- private static string[][] _isoVectors =
+ private static string[] messages =
{
- new string[]
- {
- "",
- "19FA61D75522A4669B44E39C1D2E1726C530232130D407F89AFEE0964997F7A73E83BE698B288FEBCF88E3E03C4F0757EA8964E59B63D93708B138CC42A66EB3"
- },
- new string[]
- {
- "a",
- "8ACA2602792AEC6F11A67206531FB7D7F0DFF59413145E6973C45001D0087B42D11BC645413AEFF63A42391A39145A591A92200D560195E53B478584FDAE231A"
- },
- new string[]
- {
- "abc",
- "4E2448A4C6F486BB16B6562C73B4020BF3043E3A731BCE721AE1B303D97E6D4C7181EEBDB6C57E277D0E34957114CBD6C797FC9D95D8B582D225292076D4EEF5"
- },
- new string[]
- {
- "message digest",
- "378C84A4126E2DC6E56DCC7458377AAC838D00032230F53CE1F5700C0FFB4D3B8421557659EF55C106B4B52AC5A4AAA692ED920052838F3362E86DBD37A8903E"
- },
- new string[]
- {
- "abcdefghijklmnopqrstuvwxyz",
- "F1D754662636FFE92C82EBB9212A484A8D38631EAD4238F5442EE13B8054E41B08BF2A9251C30B6A0B8AAE86177AB4A6F68F673E7207865D5D9819A3DBA4EB3B"
- },
- new string[]
- {
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
- "DC37E008CF9EE69BF11F00ED9ABA26901DD7C28CDEC066CC6AF42E40F82F3A1E08EBA26629129D8FB7CB57211B9281A65517CC879D7B962142C65F5A7AF01467"
- },
- new string[]
- {
- "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
- "466EF18BABB0154D25B9D38A6414F5C08784372BCCB204D6549C4AFADB6014294D5BD8DF2A6C44E538CD047B2681A51A2C60481E88C5A20B2C2A80CF3A9A083B"
- },
- new string[]
- {
- "abcdbcdecdefdefgefghfghighijhijk",
- "2A987EA40F917061F5D6F0A0E4644F488A7A5A52DEEE656207C562F988E95C6916BDC8031BC5BE1B7B947639FE050B56939BAAA0ADFF9AE6745B7B181C3BE3FD"
- }
+ "",
+ "a",
+ "abc",
+ "message digest",
+ "abcdefghijklmnopqrstuvwxyz",
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
+ "abcdbcdecdefdefgefghfghighijhijk"
+ };
+
+ private static string[] digests =
+ {
+ "19FA61D75522A4669B44E39C1D2E1726C530232130D407F89AFEE0964997F7A73E83BE698B288FEBCF88E3E03C4F0757EA8964E59B63D93708B138CC42A66EB3",
+ "8ACA2602792AEC6F11A67206531FB7D7F0DFF59413145E6973C45001D0087B42D11BC645413AEFF63A42391A39145A591A92200D560195E53B478584FDAE231A",
+ "4E2448A4C6F486BB16B6562C73B4020BF3043E3A731BCE721AE1B303D97E6D4C7181EEBDB6C57E277D0E34957114CBD6C797FC9D95D8B582D225292076D4EEF5",
+ "378C84A4126E2DC6E56DCC7458377AAC838D00032230F53CE1F5700C0FFB4D3B8421557659EF55C106B4B52AC5A4AAA692ED920052838F3362E86DBD37A8903E",
+ "F1D754662636FFE92C82EBB9212A484A8D38631EAD4238F5442EE13B8054E41B08BF2A9251C30B6A0B8AAE86177AB4A6F68F673E7207865D5D9819A3DBA4EB3B",
+ "DC37E008CF9EE69BF11F00ED9ABA26901DD7C28CDEC066CC6AF42E40F82F3A1E08EBA26629129D8FB7CB57211B9281A65517CC879D7B962142C65F5A7AF01467",
+ "466EF18BABB0154D25B9D38A6414F5C08784372BCCB204D6549C4AFADB6014294D5BD8DF2A6C44E538CD047B2681A51A2C60481E88C5A20B2C2A80CF3A9A083B",
+ "2A987EA40F917061F5D6F0A0E4644F488A7A5A52DEEE656207C562F988E95C6916BDC8031BC5BE1B7B947639FE050B56939BAAA0ADFF9AE6745B7B181C3BE3FD"
};
private static string _millionAResultVector = "0C99005BEB57EFF50A7CF005560DDF5D29057FD86B20BFD62DECA0F1CCEA4AF51FC15490EDDC47AF32BB2B66C34FF9AD8C6008AD677F77126953B226E4ED8B01";
private static string _thirtyOneZeros = "3E3F188F8FEBBEB17A933FEAF7FE53A4858D80C915AD6A1418F0318E68D49B4E459223CD414E0FBC8A57578FD755D86E827ABEF4070FC1503E25D99E382F72BA";
- public override string Name
+ internal WhirlpoolDigestTest()
+ : base(new WhirlpoolDigest(), messages, digests)
{
- get
- {
- return "Whirlpool";
- }
}
public override void PerformTest()
{
- for (int i = 0; i < _isoVectors.Length; i++)
- {
- performStandardVectorTest("ISO vector test ["+i+"]", _isoVectors[i][0],
- _isoVectors[i][1]);
- }
+ base.PerformTest();
byte[] thirtyOneZeros = new byte[31];
- performStandardVectorTest("31 zeroes test",
- thirtyOneZeros, _thirtyOneZeros);
+ performStandardVectorTest("31 zeroes test",
+ thirtyOneZeros, _thirtyOneZeros);
byte[] millionAInByteArray = new byte[1000000];
-// Arrays.fill(millionAInByteArray, (byte)'a');
- for (int ai = 0; ai < millionAInByteArray.Length; ++ai)
- {
- millionAInByteArray[ai] = (byte) 'a';
- }
+ Arrays.Fill(millionAInByteArray, (byte)'a');
- performStandardVectorTest("Million 'a' test",
- millionAInByteArray, _millionAResultVector);
+ performStandardVectorTest("Million 'a' test",
+ millionAInByteArray, _millionAResultVector);
}
private void performStandardVectorTest(string testTitle, byte[] inputBytes,
- string resultsAsHex)
+ string resultsAsHex)
{
- doPerformTest(testTitle, inputBytes, resultsAsHex);
+ doPerformTest(testTitle, inputBytes, resultsAsHex);
}
private void doPerformTest(string testTitle, byte[] inputBytes, string resultsAsHex)
{
string resStr = createHexOutputFromDigest(inputBytes);
- if (resultsAsHex != resStr.ToUpper())
+ if (!resultsAsHex.Equals(resStr.ToUpper()))
{
Fail(testTitle, resultsAsHex, resStr);
}
}
- private void performStandardVectorTest(string testTitle, string inputBytesAsString,
- string resultsAsHex)
- {
- doPerformTest(testTitle, Encoding.ASCII.GetBytes(inputBytesAsString), resultsAsHex);
- }
-
private string createHexOutputFromDigest(byte[] digestBytes)
{
+ string resStr;
IDigest digest = new WhirlpoolDigest();
byte[] resBuf = new byte[digest.GetDigestSize()];
digest.BlockUpdate(digestBytes, 0, digestBytes.Length);
digest.DoFinal(resBuf, 0);
- return Hex.ToHexString(resBuf);
+ resStr = Hex.ToHexString(resBuf);
+ return resStr;
+ }
+
+ protected override IDigest CloneDigest(IDigest digest)
+ {
+ return new WhirlpoolDigest((WhirlpoolDigest)digest);
}
public static void Main(
string[] args)
{
- WhirlpoolDigestTest test = new WhirlpoolDigestTest();
- ITestResult result = test.Perform();
-
- Console.WriteLine(result);
+ RunTest(new WhirlpoolDigestTest());
}
[Test]
|