From 9c25e41a757608e97edc0a0cb9443816de9d6b35 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sun, 8 Apr 2018 17:15:10 +0700 Subject: Latest scrypt updates from bc-java --- crypto/src/crypto/generators/SCrypt.cs | 42 ++++++++++++++++++++--- 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 + /// Implementation of the scrypt a password-based key derivation function. + /// + /// Scrypt was created by Colin Percival and is specified in + /// draft-josefsson-scrypt-kd. + /// + public class SCrypt { - // TODO Validate arguments - public static byte[] Generate(byte[] P, byte[] S, int N, int r, int p, int dkLen) + /// Generate a key using the scrypt key derivation function. + /// the bytes of the pass phrase. + /// the salt to use for this invocation. + /// CPU/Memory cost parameter. Must be larger than 1, a power of 2 and less than + /// 2^(128 * r / 8). + /// the block size, must be >= 1. + /// Parallelization parameter. Must be a positive integer less than or equal to + /// Int32.MaxValue / (128 * r * 8). + /// the length of the key to generate. + /// the generated key. + 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); - } } } -- cgit 1.4.1