diff options
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/src/crypto/generators/SCrypt.cs | 42 | ||||
-rw-r--r-- | crypto/test/src/crypto/test/SCryptTest.cs | 56 |
2 files changed, 86 insertions, 12 deletions
diff --git a/crypto/src/crypto/generators/SCrypt.cs b/crypto/src/crypto/generators/SCrypt.cs index efa74d735..64a36df63 100644 --- a/crypto/src/crypto/generators/SCrypt.cs +++ b/crypto/src/crypto/generators/SCrypt.cs @@ -8,12 +8,46 @@ using Org.BouncyCastle.Crypto.Utilities; namespace Org.BouncyCastle.Crypto.Generators { - public class SCrypt + /// <summary>Implementation of the scrypt a password-based key derivation function.</summary> + /// <remarks> + /// Scrypt was created by Colin Percival and is specified in + /// <a href="http://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01">draft-josefsson-scrypt-kd</a>. + /// </remarks> + public class SCrypt { - // TODO Validate arguments - public static byte[] Generate(byte[] P, byte[] S, int N, int r, int p, int dkLen) + /// <summary>Generate a key using the scrypt key derivation function.</summary> + /// <param name="P">the bytes of the pass phrase.</param> + /// <param name="S">the salt to use for this invocation.</param> + /// <param name="N">CPU/Memory cost parameter. Must be larger than 1, a power of 2 and less than + /// <code>2^(128 * r / 8)</code>.</param> + /// <param name="r">the block size, must be >= 1.</param> + /// <param name="p">Parallelization parameter. Must be a positive integer less than or equal to + /// <code>Int32.MaxValue / (128 * r * 8)</code>.</param> + /// <param name="dkLen">the length of the key to generate.</param> + /// <returns>the generated key.</returns> + public static byte[] Generate(byte[] P, byte[] S, int N, int r, int p, int dkLen) { - return MFcrypt(P, S, N, r, p, dkLen); + if (P == null) + throw new ArgumentNullException("Passphrase P must be provided."); + if (S == null) + throw new ArgumentNullException("Salt S must be provided."); + if (N <= 1) + throw new ArgumentException("Cost parameter N must be > 1."); + // Only value of r that cost (as an int) could be exceeded for is 1 + if (r == 1 && N >= 65536) + throw new ArgumentException("Cost parameter N must be > 1 and < 65536."); + if (r < 1) + throw new ArgumentException("Block size r must be >= 1."); + int maxParallel = Int32.MaxValue / (128 * r * 8); + if (p < 1 || p > maxParallel) + { + throw new ArgumentException("Parallelisation parameter p must be >= 1 and <= " + maxParallel + + " (based on block size r of " + r + ")"); + } + if (dkLen < 1) + throw new ArgumentException("Generated key length dkLen must be >= 1."); + + return MFcrypt(P, S, N, r, p, dkLen); } private static byte[] MFcrypt(byte[] P, byte[] S, int N, int r, int p, int dkLen) diff --git a/crypto/test/src/crypto/test/SCryptTest.cs b/crypto/test/src/crypto/test/SCryptTest.cs index c055ab718..82bc60880 100644 --- a/crypto/test/src/crypto/test/SCryptTest.cs +++ b/crypto/test/src/crypto/test/SCryptTest.cs @@ -26,6 +26,54 @@ namespace Org.BouncyCastle.Crypto.Tests public override void PerformTest() { + TestParameters(); + TestVectors(); + } + + [Test] + public void TestParameters() + { + CheckOK("Minimal values", new byte[0], new byte[0], 2, 1, 1, 1); + CheckIllegal("Cost parameter must be > 1", new byte[0], new byte[0], 1, 1, 1, 1); + CheckOK("Cost parameter 32768 OK for r == 1", new byte[0], new byte[0], 32768, 1, 1, 1); + CheckIllegal("Cost parameter must < 65536 for r == 1", new byte[0], new byte[0], 65536, 1, 1, 1); + CheckIllegal("Block size must be >= 1", new byte[0], new byte[0], 2, 0, 2, 1); + CheckIllegal("Parallelisation parameter must be >= 1", new byte[0], new byte[0], 2, 1, 0, 1); + // CheckOK("Parallelisation parameter 65535 OK for r = 4", new byte[0], new byte[0], 2, 32, 65535, 1); + CheckIllegal("Parallelisation parameter must be < 65535 for r = 4", new byte[0], new byte[0], 2, 32, 65536, 1); + + CheckIllegal("Len parameter must be > 1", new byte[0], new byte[0], 2, 1, 1, 0); + } + + private void CheckOK(String msg, byte[] pass, byte[] salt, int N, int r, int p, int len) + { + try + { + SCrypt.Generate(pass, salt, N, r, p, len); + } + catch (ArgumentException e) + { + Console.Error.WriteLine(e.StackTrace); + Fail(msg); + } + } + + private void CheckIllegal(String msg, byte[] pass, byte[] salt, int N, int r, int p, int len) + { + try + { + SCrypt.Generate(pass, salt, N, r, p, len); + Fail(msg); + } + catch (ArgumentException e) + { + //Console.Error.WriteLine(e.StackTrace); + } + } + + [Test] + public void TestVectors() + { using (StreamReader sr = new StreamReader(SimpleTest.GetTestDataAsStream("scrypt.TestVectors.txt"))) { int count = 0; @@ -91,13 +139,5 @@ namespace Org.BouncyCastle.Crypto.Tests { RunTest(new SCryptTest()); } - - [Test] - public void TestFunction() - { - string resultText = Perform().ToString(); - - Assert.AreEqual(Name + ": Okay", resultText); - } } } |