From b7039a1a635e7b74765d44d2caf8cc2c5f66a6bc Mon Sep 17 00:00:00 2001 From: Jeffrey Stedfast Date: Tue, 14 Oct 2014 14:50:29 -0400 Subject: Added Visual Studio 2010 project/solution files for .NET 2.0 and Xamarin Android/iOS --- crypto/test/src/util/test/SimpleTest.cs | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'crypto/test/src') diff --git a/crypto/test/src/util/test/SimpleTest.cs b/crypto/test/src/util/test/SimpleTest.cs index be846e20f..bcbfa2a5b 100644 --- a/crypto/test/src/util/test/SimpleTest.cs +++ b/crypto/test/src/util/test/SimpleTest.cs @@ -115,23 +115,13 @@ namespace Org.BouncyCastle.Utilities.Test private static string GetFullName( string name) { -// TODO MonoDevelop/Visual Studio embedded resource ids still inconsistent -#if BC_BUILD_MONODEVELOP - return "test.data." + name; -#else - return "crypto.test.data." + name; -#endif + return "UnitTests.data." + name; } private static string GetShortName( string fullName) { -// TODO MonoDevelop/Visual Studio embedded resource ids still inconsistent -#if BC_BUILD_MONODEVELOP - return fullName.Substring("test.data.".Length); -#else - return fullName.Substring("crypto.test.data.".Length); -#endif + return fullName.Substring("UnitTests.data.".Length); } #if NETCF_1_0 || NETCF_2_0 -- cgit 1.5.1 From 9a03d17b9f14eebe162c67bcf12f8e6f648ee0e9 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 9 Nov 2015 12:10:05 +0700 Subject: A few changes in the use of LIB preprocessor flag --- crypto/test/src/crypto/agreement/test/AllTests.cs | 4 +++- crypto/test/src/openssl/test/AllTests.cs | 6 ++++-- crypto/test/src/util/io/pem/test/AllTests.cs | 6 ++++-- 3 files changed, 11 insertions(+), 5 deletions(-) (limited to 'crypto/test/src') diff --git a/crypto/test/src/crypto/agreement/test/AllTests.cs b/crypto/test/src/crypto/agreement/test/AllTests.cs index ea8f438e5..66853b285 100644 --- a/crypto/test/src/crypto/agreement/test/AllTests.cs +++ b/crypto/test/src/crypto/agreement/test/AllTests.cs @@ -1,4 +1,5 @@ -using System; +#if !LIB +using System; using NUnit.Core; using NUnit.Framework; @@ -29,3 +30,4 @@ namespace Org.BouncyCastle.Crypto.Agreement.Tests } } } +#endif diff --git a/crypto/test/src/openssl/test/AllTests.cs b/crypto/test/src/openssl/test/AllTests.cs index 871b926b8..0cc2dcd85 100644 --- a/crypto/test/src/openssl/test/AllTests.cs +++ b/crypto/test/src/openssl/test/AllTests.cs @@ -1,9 +1,10 @@ -#if !LIB using System; using System.IO; using System.Text; +#if !LIB using NUnit.Core; +#endif using NUnit.Framework; using Org.BouncyCastle.Crypto; @@ -34,6 +35,7 @@ namespace Org.BouncyCastle.OpenSsl.Tests } } +#if !LIB public static void Main(string[] args) { Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty); @@ -49,6 +51,7 @@ namespace Org.BouncyCastle.OpenSsl.Tests return suite; } } +#endif [Test] public void TestOpenSsl() @@ -129,4 +132,3 @@ namespace Org.BouncyCastle.OpenSsl.Tests } } } -#endif diff --git a/crypto/test/src/util/io/pem/test/AllTests.cs b/crypto/test/src/util/io/pem/test/AllTests.cs index 5f0c12c10..921c40cb8 100644 --- a/crypto/test/src/util/io/pem/test/AllTests.cs +++ b/crypto/test/src/util/io/pem/test/AllTests.cs @@ -1,11 +1,12 @@ -#if !LIB using System; using System.Collections; using System.Collections.Specialized; using System.IO; using System.Text; +#if !LIB using NUnit.Core; +#endif using NUnit.Framework; using Org.BouncyCastle.Crypto; @@ -20,6 +21,7 @@ namespace Org.BouncyCastle.Utilities.IO.Pem.Tests [TestFixture] public class AllTests { +#if !LIB public static void Main(string[] args) { Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty); @@ -35,6 +37,7 @@ namespace Org.BouncyCastle.Utilities.IO.Pem.Tests return suite; } } +#endif [Test] public void TestPemLength() @@ -73,4 +76,3 @@ namespace Org.BouncyCastle.Utilities.IO.Pem.Tests } } } -#endif -- cgit 1.5.1 From 36057f66032c5e2942a8c3797be39f20693318f3 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 9 Nov 2015 12:10:58 +0700 Subject: Add DOTNET and LIB preprocessor flags as per BouncyCastle-PCL --- crypto/src/cms/CMSProcessableFile.cs | 2 +- crypto/src/openpgp/PgpLiteralDataGenerator.cs | 4 ++-- crypto/src/openpgp/PgpUtilities.cs | 2 +- crypto/test/src/asn1/test/AllTests.cs | 2 ++ crypto/test/src/cms/test/AllTests.cs | 2 ++ crypto/test/src/crypto/agreement/test/AllTests.cs | 4 +++- crypto/test/src/crypto/io/test/AllTests.cs | 2 ++ crypto/test/src/crypto/test/AllTests.cs | 4 ++++ crypto/test/src/math/ec/test/AllTests.cs | 2 ++ crypto/test/src/math/test/AllTests.cs | 2 ++ crypto/test/src/ocsp/test/AllTests.cs | 2 ++ crypto/test/src/openpgp/examples/test/AllTests.cs | 2 ++ crypto/test/src/openssl/test/AllTests.cs | 4 ++++ crypto/test/src/tsp/test/AllTests.cs | 2 ++ crypto/test/src/util/io/pem/test/AllTests.cs | 4 ++++ 15 files changed, 35 insertions(+), 5 deletions(-) (limited to 'crypto/test/src') diff --git a/crypto/src/cms/CMSProcessableFile.cs b/crypto/src/cms/CMSProcessableFile.cs index b514bdbda..c74d2a846 100644 --- a/crypto/src/cms/CMSProcessableFile.cs +++ b/crypto/src/cms/CMSProcessableFile.cs @@ -1,4 +1,4 @@ -#if !PORTABLE +#if !PORTABLE || DOTNET using System; using System.IO; diff --git a/crypto/src/openpgp/PgpLiteralDataGenerator.cs b/crypto/src/openpgp/PgpLiteralDataGenerator.cs index 17a6eeef2..7672659ca 100644 --- a/crypto/src/openpgp/PgpLiteralDataGenerator.cs +++ b/crypto/src/openpgp/PgpLiteralDataGenerator.cs @@ -141,8 +141,8 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp return new WrappedGeneratorStream(this, pkOut); } -#if !PORTABLE - /// +#if !PORTABLE || DOTNET + /// ///

/// Open a literal data packet for the passed in FileInfo object, returning /// an output stream for saving the file contents. diff --git a/crypto/src/openpgp/PgpUtilities.cs b/crypto/src/openpgp/PgpUtilities.cs index 9238edcfc..055f99636 100644 --- a/crypto/src/openpgp/PgpUtilities.cs +++ b/crypto/src/openpgp/PgpUtilities.cs @@ -347,7 +347,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp return MakeKey(algorithm, keyBytes); } -#if !PORTABLE +#if !PORTABLE || DOTNET ///

Write out the passed in file as a literal data packet. public static void WriteFileToLiteralData( Stream output, diff --git a/crypto/test/src/asn1/test/AllTests.cs b/crypto/test/src/asn1/test/AllTests.cs index ad2f90362..981b5a4df 100644 --- a/crypto/test/src/asn1/test/AllTests.cs +++ b/crypto/test/src/asn1/test/AllTests.cs @@ -1,3 +1,4 @@ +#if !LIB using System; using NUnit.Core; @@ -28,3 +29,4 @@ namespace Org.BouncyCastle.Asn1.Tests } } } +#endif diff --git a/crypto/test/src/cms/test/AllTests.cs b/crypto/test/src/cms/test/AllTests.cs index b7ac7644b..b47374914 100644 --- a/crypto/test/src/cms/test/AllTests.cs +++ b/crypto/test/src/cms/test/AllTests.cs @@ -1,3 +1,4 @@ +#if !LIB using System; using NUnit.Core; @@ -32,3 +33,4 @@ namespace Org.BouncyCastle.Cms.Tests } } } +#endif diff --git a/crypto/test/src/crypto/agreement/test/AllTests.cs b/crypto/test/src/crypto/agreement/test/AllTests.cs index ea8f438e5..66853b285 100644 --- a/crypto/test/src/crypto/agreement/test/AllTests.cs +++ b/crypto/test/src/crypto/agreement/test/AllTests.cs @@ -1,4 +1,5 @@ -using System; +#if !LIB +using System; using NUnit.Core; using NUnit.Framework; @@ -29,3 +30,4 @@ namespace Org.BouncyCastle.Crypto.Agreement.Tests } } } +#endif diff --git a/crypto/test/src/crypto/io/test/AllTests.cs b/crypto/test/src/crypto/io/test/AllTests.cs index 5c8c759f9..2634b4ab1 100644 --- a/crypto/test/src/crypto/io/test/AllTests.cs +++ b/crypto/test/src/crypto/io/test/AllTests.cs @@ -1,3 +1,4 @@ +#if !LIB using System; using NUnit.Core; @@ -24,3 +25,4 @@ namespace Org.BouncyCastle.Crypto.IO.Tests } } } +#endif diff --git a/crypto/test/src/crypto/test/AllTests.cs b/crypto/test/src/crypto/test/AllTests.cs index 3d8ef5602..e7035a663 100644 --- a/crypto/test/src/crypto/test/AllTests.cs +++ b/crypto/test/src/crypto/test/AllTests.cs @@ -1,6 +1,8 @@ using System; +#if !LIB using NUnit.Core; +#endif using NUnit.Framework; using Org.BouncyCastle.Utilities.Test; @@ -10,6 +12,7 @@ namespace Org.BouncyCastle.Crypto.Tests [TestFixture] public class AllTests { +#if !LIB public static void Main(string[] args) { Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty); @@ -26,6 +29,7 @@ namespace Org.BouncyCastle.Crypto.Tests return suite; } } +#endif [Test] public void TestCrypto() diff --git a/crypto/test/src/math/ec/test/AllTests.cs b/crypto/test/src/math/ec/test/AllTests.cs index 3e014ffd2..0517ac713 100644 --- a/crypto/test/src/math/ec/test/AllTests.cs +++ b/crypto/test/src/math/ec/test/AllTests.cs @@ -1,3 +1,4 @@ +#if !LIB using System; using NUnit.Core; @@ -25,3 +26,4 @@ namespace Org.BouncyCastle.Math.EC.Tests } } } +#endif diff --git a/crypto/test/src/math/test/AllTests.cs b/crypto/test/src/math/test/AllTests.cs index 2bcc129ea..53feff954 100644 --- a/crypto/test/src/math/test/AllTests.cs +++ b/crypto/test/src/math/test/AllTests.cs @@ -1,3 +1,4 @@ +#if !LIB using System; using NUnit.Core; @@ -25,3 +26,4 @@ namespace Org.BouncyCastle.Math.Tests } } } +#endif diff --git a/crypto/test/src/ocsp/test/AllTests.cs b/crypto/test/src/ocsp/test/AllTests.cs index 5e919fd91..5e799cd09 100644 --- a/crypto/test/src/ocsp/test/AllTests.cs +++ b/crypto/test/src/ocsp/test/AllTests.cs @@ -1,3 +1,4 @@ +#if !LIB using System; using NUnit.Core; @@ -26,3 +27,4 @@ namespace Org.BouncyCastle.Ocsp.Tests } } } +#endif diff --git a/crypto/test/src/openpgp/examples/test/AllTests.cs b/crypto/test/src/openpgp/examples/test/AllTests.cs index 9a515ea15..3403a4fdc 100644 --- a/crypto/test/src/openpgp/examples/test/AllTests.cs +++ b/crypto/test/src/openpgp/examples/test/AllTests.cs @@ -1,3 +1,4 @@ +#if !LIB using System; using System.IO; @@ -434,3 +435,4 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples.Tests } } } +#endif diff --git a/crypto/test/src/openssl/test/AllTests.cs b/crypto/test/src/openssl/test/AllTests.cs index f843d0479..0cc2dcd85 100644 --- a/crypto/test/src/openssl/test/AllTests.cs +++ b/crypto/test/src/openssl/test/AllTests.cs @@ -2,7 +2,9 @@ using System; using System.IO; using System.Text; +#if !LIB using NUnit.Core; +#endif using NUnit.Framework; using Org.BouncyCastle.Crypto; @@ -33,6 +35,7 @@ namespace Org.BouncyCastle.OpenSsl.Tests } } +#if !LIB public static void Main(string[] args) { Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty); @@ -48,6 +51,7 @@ namespace Org.BouncyCastle.OpenSsl.Tests return suite; } } +#endif [Test] public void TestOpenSsl() diff --git a/crypto/test/src/tsp/test/AllTests.cs b/crypto/test/src/tsp/test/AllTests.cs index 3e8b0cd5e..58d096d54 100644 --- a/crypto/test/src/tsp/test/AllTests.cs +++ b/crypto/test/src/tsp/test/AllTests.cs @@ -1,3 +1,4 @@ +#if !LIB using System; using NUnit.Core; @@ -29,3 +30,4 @@ namespace Org.BouncyCastle.Tsp.Tests } } } +#endif diff --git a/crypto/test/src/util/io/pem/test/AllTests.cs b/crypto/test/src/util/io/pem/test/AllTests.cs index c36f79304..921c40cb8 100644 --- a/crypto/test/src/util/io/pem/test/AllTests.cs +++ b/crypto/test/src/util/io/pem/test/AllTests.cs @@ -4,7 +4,9 @@ using System.Collections.Specialized; using System.IO; using System.Text; +#if !LIB using NUnit.Core; +#endif using NUnit.Framework; using Org.BouncyCastle.Crypto; @@ -19,6 +21,7 @@ namespace Org.BouncyCastle.Utilities.IO.Pem.Tests [TestFixture] public class AllTests { +#if !LIB public static void Main(string[] args) { Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty); @@ -34,6 +37,7 @@ namespace Org.BouncyCastle.Utilities.IO.Pem.Tests return suite; } } +#endif [Test] public void TestPemLength() -- cgit 1.5.1 From 077d073d23766583391b8241e8db262bc8619b5d Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Tue, 10 Nov 2015 13:09:14 +0700 Subject: Add more PkiFailureInfo constants --- crypto/src/asn1/cmp/PKIFailureInfo.cs | 114 ++++++++++++++---------- crypto/test/src/asn1/test/PKIFailureInfoTest.cs | 53 ++++++----- 2 files changed, 102 insertions(+), 65 deletions(-) (limited to 'crypto/test/src') diff --git a/crypto/src/asn1/cmp/PKIFailureInfo.cs b/crypto/src/asn1/cmp/PKIFailureInfo.cs index 1df0e0693..896bf0992 100644 --- a/crypto/src/asn1/cmp/PKIFailureInfo.cs +++ b/crypto/src/asn1/cmp/PKIFailureInfo.cs @@ -2,55 +2,79 @@ using System; namespace Org.BouncyCastle.Asn1.Cmp { - /** - *
-	 * PKIFailureInfo ::= BIT STRING {
-	 * badAlg               (0),
-	 *   -- unrecognized or unsupported Algorithm Identifier
-	 * badMessageCheck      (1), -- integrity check failed (e.g., signature did not verify)
-	 * badRequest           (2),
-	 *   -- transaction not permitted or supported
-	 * badTime              (3), -- messageTime was not sufficiently close to the system time, as defined by local policy
-	 * badCertId            (4), -- no certificate could be found matching the provided criteria
-	 * badDataFormat        (5),
-	 *   -- the data submitted has the wrong format
-	 * wrongAuthority       (6), -- the authority indicated in the request is different from the one creating the response token
-	 * incorrectData        (7), -- the requester's data is incorrect (for notary services)
-	 * missingTimeStamp     (8), -- when the timestamp is missing but should be there (by policy)
-	 * badPOP               (9)  -- the proof-of-possession failed
-	 * timeNotAvailable    (14),
-	 *   -- the TSA's time source is not available
-	 * unacceptedPolicy    (15),
-	 *   -- the requested TSA policy is not supported by the TSA
-	 * unacceptedExtension (16),
-	 *   -- the requested extension is not supported by the TSA
-	 *  addInfoNotAvailable (17)
-	 *    -- the additional information requested could not be understood
-	 *    -- or is not available
-	 *  systemFailure       (25)
-	 *    -- the request cannot be handled due to system failure
-	 * 
- */ + /** + *
+     * PKIFailureInfo ::= BIT STRING {
+     * badAlg               (0),
+     *   -- unrecognized or unsupported Algorithm Identifier
+     * badMessageCheck      (1), -- integrity check failed (e.g., signature did not verify)
+     * badRequest           (2),
+     *   -- transaction not permitted or supported
+     * badTime              (3), -- messageTime was not sufficiently close to the system time, as defined by local policy
+     * badCertId            (4), -- no certificate could be found matching the provided criteria
+     * badDataFormat        (5),
+     *   -- the data submitted has the wrong format
+     * wrongAuthority       (6), -- the authority indicated in the request is different from the one creating the response token
+     * incorrectData        (7), -- the requester's data is incorrect (for notary services)
+     * missingTimeStamp     (8), -- when the timestamp is missing but should be there (by policy)
+     * badPOP               (9)  -- the proof-of-possession failed
+     * certRevoked         (10),
+     * certConfirmed       (11),
+     * wrongIntegrity      (12),
+     * badRecipientNonce   (13), 
+     * timeNotAvailable    (14),
+     *   -- the TSA's time source is not available
+     * unacceptedPolicy    (15),
+     *   -- the requested TSA policy is not supported by the TSA
+     * unacceptedExtension (16),
+     *   -- the requested extension is not supported by the TSA
+     * addInfoNotAvailable (17)
+     *   -- the additional information requested could not be understood
+     *   -- or is not available
+     * badSenderNonce      (18),
+     * badCertTemplate     (19),
+     * signerNotTrusted    (20),
+     * transactionIdInUse  (21),
+     * unsupportedVersion  (22),
+     * notAuthorized       (23),
+     * systemUnavail       (24),    
+     * systemFailure       (25),
+     *   -- the request cannot be handled due to system failure
+     * duplicateCertReq    (26) 
+     * 
+ */ public class PkiFailureInfo : DerBitString { - public const int BadAlg = (1 << 7); // unrecognized or unsupported Algorithm Identifier - public const int BadMessageCheck = (1 << 6); // integrity check failed (e.g., signature did not verify) - public const int BadRequest = (1 << 5); - public const int BadTime = (1 << 4); // -- messageTime was not sufficiently close to the system time, as defined by local policy - public const int BadCertId = (1 << 3); // no certificate could be found matching the provided criteria - public const int BadDataFormat = (1 << 2); - public const int WrongAuthority = (1 << 1); // the authority indicated in the request is different from the one creating the response token - public const int IncorrectData = 1; // the requester's data is incorrect (for notary services) - public const int MissingTimeStamp = (1 << 15); // when the timestamp is missing but should be there (by policy) - public const int BadPop = (1 << 14); // the proof-of-possession failed - public const int TimeNotAvailable = (1 << 9); // the TSA's time source is not available - public const int UnacceptedPolicy = (1 << 8); // the requested TSA policy is not supported by the TSA - public const int UnacceptedExtension = (1 << 23); //the requested extension is not supported by the TSA - public const int AddInfoNotAvailable = (1 << 22); //the additional information requested could not be understood or is not available - public const int SystemFailure = (1 << 30); //the request cannot be handled due to system failure + public const int BadAlg = (1 << 7); // unrecognized or unsupported Algorithm Identifier + public const int BadMessageCheck = (1 << 6); // integrity check failed (e.g., signature did not verify) + public const int BadRequest = (1 << 5); + public const int BadTime = (1 << 4); // -- messageTime was not sufficiently close to the system time, as defined by local policy + public const int BadCertId = (1 << 3); // no certificate could be found matching the provided criteria + public const int BadDataFormat = (1 << 2); + public const int WrongAuthority = (1 << 1); // the authority indicated in the request is different from the one creating the response token + public const int IncorrectData = 1; // the requester's data is incorrect (for notary services) + public const int MissingTimeStamp = (1 << 15); // when the timestamp is missing but should be there (by policy) + public const int BadPop = (1 << 14); // the proof-of-possession failed + public const int CertRevoked = (1 << 13); + public const int CertConfirmed = (1 << 12); + public const int WrongIntegrity = (1 << 11); + public const int BadRecipientNonce = (1 << 10); + public const int TimeNotAvailable = (1 << 9); // the TSA's time source is not available + public const int UnacceptedPolicy = (1 << 8); // the requested TSA policy is not supported by the TSA + public const int UnacceptedExtension = (1 << 23); //the requested extension is not supported by the TSA + public const int AddInfoNotAvailable = (1 << 22); //the additional information requested could not be understood or is not available + public const int BadSenderNonce = (1 << 21); + public const int BadCertTemplate = (1 << 20); + public const int SignerNotTrusted = (1 << 19); + public const int TransactionIdInUse = (1 << 18); + public const int UnsupportedVersion = (1 << 17); + public const int NotAuthorized = (1 << 16); + public const int SystemUnavail = (1 << 31); + public const int SystemFailure = (1 << 30); //the request cannot be handled due to system failure + public const int DuplicateCertReq = (1 << 29); - /** + /** * Basic constructor. */ public PkiFailureInfo( diff --git a/crypto/test/src/asn1/test/PKIFailureInfoTest.cs b/crypto/test/src/asn1/test/PKIFailureInfoTest.cs index 734dbbc14..7d51dbb5f 100644 --- a/crypto/test/src/asn1/test/PKIFailureInfoTest.cs +++ b/crypto/test/src/asn1/test/PKIFailureInfoTest.cs @@ -11,7 +11,7 @@ using Org.BouncyCastle.Utilities.Test; namespace Org.BouncyCastle.Asn1.Tests { /** - * PKIFailureInfoTest + * PkiFailureInfoTest */ [TestFixture] public class PkiFailureInfoTest @@ -25,12 +25,13 @@ namespace Org.BouncyCastle.Asn1.Tests get { return "PkiFailureInfo"; } } - private void doTestEncoding() + private void DoTestEncoding() { - DerBitString bitString = (DerBitString) Asn1Object.FromByteArray(CORRECT_FAILURE_INFO); + DerBitString bitString = (DerBitString)Asn1Object.FromByteArray(CORRECT_FAILURE_INFO); PkiFailureInfo correct = new PkiFailureInfo(bitString); - PkiFailureInfo bug = new PkiFailureInfo(PkiFailureInfo.BadRequest | PkiFailureInfo.BadTime | PkiFailureInfo.BadDataFormat | PkiFailureInfo.IncorrectData); + PkiFailureInfo bug = new PkiFailureInfo( + PkiFailureInfo.BadRequest | PkiFailureInfo.BadTime | PkiFailureInfo.BadDataFormat | PkiFailureInfo.IncorrectData); if (!Arrays.AreEqual(correct.GetDerEncoded(), bug.GetDerEncoded())) { @@ -40,23 +41,35 @@ namespace Org.BouncyCastle.Asn1.Tests public override void PerformTest() { - BitStringConstantTester.testFlagValueCorrect(0, PkiFailureInfo.BadAlg); - BitStringConstantTester.testFlagValueCorrect(1, PkiFailureInfo.BadMessageCheck); - BitStringConstantTester.testFlagValueCorrect(2, PkiFailureInfo.BadRequest); - BitStringConstantTester.testFlagValueCorrect(3, PkiFailureInfo.BadTime); - BitStringConstantTester.testFlagValueCorrect(4, PkiFailureInfo.BadCertId); - BitStringConstantTester.testFlagValueCorrect(5, PkiFailureInfo.BadDataFormat); - BitStringConstantTester.testFlagValueCorrect(6, PkiFailureInfo.WrongAuthority); - BitStringConstantTester.testFlagValueCorrect(7, PkiFailureInfo.IncorrectData); - BitStringConstantTester.testFlagValueCorrect(8, PkiFailureInfo.MissingTimeStamp); - BitStringConstantTester.testFlagValueCorrect(9, PkiFailureInfo.BadPop); - BitStringConstantTester.testFlagValueCorrect(14, PkiFailureInfo.TimeNotAvailable); - BitStringConstantTester.testFlagValueCorrect(15, PkiFailureInfo.UnacceptedPolicy); - BitStringConstantTester.testFlagValueCorrect(16, PkiFailureInfo.UnacceptedExtension); - BitStringConstantTester.testFlagValueCorrect(17, PkiFailureInfo.AddInfoNotAvailable); - BitStringConstantTester.testFlagValueCorrect(25, PkiFailureInfo.SystemFailure); + BitStringConstantTester.testFlagValueCorrect(0, PkiFailureInfo.BadAlg); + BitStringConstantTester.testFlagValueCorrect(1, PkiFailureInfo.BadMessageCheck); + BitStringConstantTester.testFlagValueCorrect(2, PkiFailureInfo.BadRequest); + BitStringConstantTester.testFlagValueCorrect(3, PkiFailureInfo.BadTime); + BitStringConstantTester.testFlagValueCorrect(4, PkiFailureInfo.BadCertId); + BitStringConstantTester.testFlagValueCorrect(5, PkiFailureInfo.BadDataFormat); + BitStringConstantTester.testFlagValueCorrect(6, PkiFailureInfo.WrongAuthority); + BitStringConstantTester.testFlagValueCorrect(7, PkiFailureInfo.IncorrectData); + BitStringConstantTester.testFlagValueCorrect(8, PkiFailureInfo.MissingTimeStamp); + BitStringConstantTester.testFlagValueCorrect(9, PkiFailureInfo.BadPop); + BitStringConstantTester.testFlagValueCorrect(10, PkiFailureInfo.CertRevoked); + BitStringConstantTester.testFlagValueCorrect(11, PkiFailureInfo.CertConfirmed); + BitStringConstantTester.testFlagValueCorrect(12, PkiFailureInfo.WrongIntegrity); + BitStringConstantTester.testFlagValueCorrect(13, PkiFailureInfo.BadRecipientNonce); + BitStringConstantTester.testFlagValueCorrect(14, PkiFailureInfo.TimeNotAvailable); + BitStringConstantTester.testFlagValueCorrect(15, PkiFailureInfo.UnacceptedPolicy); + BitStringConstantTester.testFlagValueCorrect(16, PkiFailureInfo.UnacceptedExtension); + BitStringConstantTester.testFlagValueCorrect(17, PkiFailureInfo.AddInfoNotAvailable); + BitStringConstantTester.testFlagValueCorrect(18, PkiFailureInfo.BadSenderNonce); + BitStringConstantTester.testFlagValueCorrect(19, PkiFailureInfo.BadCertTemplate); + BitStringConstantTester.testFlagValueCorrect(20, PkiFailureInfo.SignerNotTrusted); + BitStringConstantTester.testFlagValueCorrect(21, PkiFailureInfo.TransactionIdInUse); + BitStringConstantTester.testFlagValueCorrect(22, PkiFailureInfo.UnsupportedVersion); + BitStringConstantTester.testFlagValueCorrect(23, PkiFailureInfo.NotAuthorized); + BitStringConstantTester.testFlagValueCorrect(24, PkiFailureInfo.SystemUnavail); + BitStringConstantTester.testFlagValueCorrect(25, PkiFailureInfo.SystemFailure); + BitStringConstantTester.testFlagValueCorrect(26, PkiFailureInfo.DuplicateCertReq); - doTestEncoding(); + DoTestEncoding(); } public static void Main( -- cgit 1.5.1 From c4f02c22b53e19a2445ee13865dc5e0e04c84359 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Tue, 10 Nov 2015 19:13:38 +0700 Subject: Add BerBitString and improve "unused bit" handling --- crypto/crypto.csproj | 5 + crypto/src/asn1/BERBitString.cs | 43 ++++ crypto/src/asn1/DerBitString.cs | 263 +++++++++++---------- crypto/src/asn1/DerOutputStream.cs | 19 +- crypto/src/asn1/cmp/PKIFailureInfo.cs | 7 +- crypto/src/asn1/misc/NetscapeCertType.cs | 2 +- crypto/src/asn1/ocsp/BasicOCSPResponse.cs | 7 +- crypto/src/asn1/ocsp/Signature.cs | 7 +- crypto/src/asn1/pkcs/CertificationRequest.cs | 7 +- crypto/src/asn1/x509/AttributeCertificate.cs | 7 +- crypto/src/asn1/x509/CertificateList.cs | 7 +- crypto/src/asn1/x509/KeyUsage.cs | 5 +- crypto/src/asn1/x509/ReasonFlags.cs | 7 +- crypto/src/asn1/x509/SubjectPublicKeyInfo.cs | 2 +- crypto/src/asn1/x509/X509CertificateStructure.cs | 5 + crypto/src/math/BigInteger.cs | 2 +- crypto/src/ocsp/BasicOCSPResp.cs | 2 +- crypto/src/ocsp/OCSPReq.cs | 4 +- crypto/src/pkcs/Pkcs10CertificationRequest.cs | 2 +- crypto/src/tsp/TimeStampResponseGenerator.cs | 5 +- crypto/src/x509/X509Certificate.cs | 4 +- crypto/src/x509/X509Crl.cs | 2 +- crypto/src/x509/X509V2AttributeCertificate.cs | 7 +- crypto/test/src/asn1/test/BitStringTest.cs | 118 +++++++-- .../test/src/crypto/tls/test/TlsTestClientImpl.cs | 6 +- crypto/test/src/test/PKCS10CertRequestTest.cs | 6 +- 26 files changed, 373 insertions(+), 178 deletions(-) create mode 100644 crypto/src/asn1/BERBitString.cs (limited to 'crypto/test/src') diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index a1e217aca..3f942800c 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -248,6 +248,11 @@ SubType = "Code" BuildAction = "Compile" /> + = 0; i--) - { - // - // this may look a little odd, but if it isn't done like this pre jdk1.2 - // JVM's break! - // - if (i != 0) - { - if ((bitString >> (i * 8)) != 0) - { - val = (bitString >> (i * 8)) & 0xFF; - break; - } - } - else - { - if (bitString != 0) - { - val = bitString & 0xFF; - break; - } - } - } - - if (val == 0) - { - return 7; - } - - int bits = 1; - - while (((val <<= 1) & 0xFF) != 0) - { - bits++; - } - - return 8 - bits; - } - - /** - * return the correct number of bytes for a bit string defined in - * a 32 bit constant - */ - static internal byte[] GetBytes( - int bitString) - { - int bytes = 4; - for (int i = 3; i >= 1; i--) - { - if ((bitString & (0xFF << (i * 8))) != 0) - { - break; - } - bytes--; - } - - byte[] result = new byte[bytes]; - for (int i = 0; i < bytes; i++) - { - result[i] = (byte) ((bitString >> (i * 8)) & 0xFF); - } - - return result; - } - - /** + /** * return a Bit string from the passed in object * * @exception ArgumentException if the object cannot be converted. @@ -126,15 +55,7 @@ namespace Org.BouncyCastle.Asn1 return FromAsn1Octets(((Asn1OctetString)o).GetOctets()); } - internal DerBitString( - byte data, - int padBits) - { - this.data = new byte[]{ data }; - this.padBits = padBits; - } - - /** + /** * @param data the octets making up the bit string. * @param padBits the number of extra bits at the end of the string. */ @@ -142,67 +63,154 @@ namespace Org.BouncyCastle.Asn1 byte[] data, int padBits) { - // TODO Deep copy? - this.data = data; - this.padBits = padBits; + if (data == null) + throw new ArgumentNullException("data"); + if (padBits < 0 || padBits > 7) + throw new ArgumentException("must be in the range 0 to 7", "padBits"); + if (data.Length == 0 && padBits != 0) + throw new ArgumentException("if 'data' is empty, 'padBits' must be 0"); + + this.mData = Arrays.Clone(data); + this.mPadBits = padBits; } public DerBitString( byte[] data) + : this(data, 0) { - // TODO Deep copy? - this.data = data; } - public DerBitString( + public DerBitString( + int namedBits) + { + if (namedBits == 0) + { + this.mData = new byte[0]; + this.mPadBits = 0; + return; + } + + int bits = BigInteger.BitLen(namedBits); + int bytes = (bits + 7) / 8; + + Debug.Assert(0 < bytes && bytes <= 4); + + byte[] result = new byte[bytes]; + --bytes; + + for (int i = 0; i < bytes; i++) + { + result[i] = (byte)namedBits; + namedBits >>= 8; + } + + Debug.Assert((namedBits & 0xFF) != 0); + + result[bytes] = (byte)namedBits; + + int pad = 0; + while ((namedBits & (1 << pad)) == 0) + { + ++pad; + } + + Debug.Assert(pad < 8); + + this.mData = result; + this.mPadBits = pad; + } + + public DerBitString( Asn1Encodable obj) + : this(obj.GetDerEncoded()) { - this.data = obj.GetDerEncoded(); - //this.padBits = 0; } - public byte[] GetBytes() + /** + * Return the octets contained in this BIT STRING, checking that this BIT STRING really + * does represent an octet aligned string. Only use this method when the standard you are + * following dictates that the BIT STRING will be octet aligned. + * + * @return a copy of the octet aligned data. + */ + public virtual byte[] GetOctets() + { + if (mPadBits != 0) + throw new InvalidOperationException("attempt to get non-octet aligned data from BIT STRING"); + + return Arrays.Clone(mData); + } + + public virtual byte[] GetBytes() { - return data; + byte[] data = Arrays.Clone(mData); + + // DER requires pad bits be zero + if (mPadBits > 0) + { + data[data.Length - 1] &= (byte)(0xFF << mPadBits); + } + + return data; } - public int PadBits + public virtual int PadBits { - get { return padBits; } + get { return mPadBits; } } /** * @return the value of the bit string as an int (truncating if necessary) */ - public int IntValue + public virtual int IntValue { get { - int value = 0; - - for (int i = 0; i != data.Length && i != 4; i++) - { - value |= (data[i] & 0xff) << (8 * i); - } - - return value; + int value = 0, length = System.Math.Min(4, mData.Length); + for (int i = 0; i < length; ++i) + { + value |= (int)mData[i] << (8 * i); + } + if (mPadBits > 0 && length == mData.Length) + { + int mask = (1 << mPadBits) - 1; + value &= ~(mask << (8 * (length - 1))); + } + return value; } } - internal override void Encode( + internal override void Encode( DerOutputStream derOut) { - byte[] bytes = new byte[GetBytes().Length + 1]; - - bytes[0] = (byte) PadBits; - Array.Copy(GetBytes(), 0, bytes, 1, bytes.Length - 1); - - derOut.WriteEncoded(Asn1Tags.BitString, bytes); + if (mPadBits > 0) + { + int last = mData[mData.Length - 1]; + int mask = (1 << mPadBits) - 1; + + if ((last & mask) != 0) + { + byte[] result = Arrays.Prepend(mData, (byte)mPadBits); + + /* + * X.690-0207 11.2.1: Each unused bit in the final octet of the encoding of a bit string value shall be set to zero. + * + * NOTE: 'pad' is constrained to be 0 if 'bytes' are empty, in which case this is a no-op. + */ + last ^= (last & mask); + result[result.Length - 1] &= (byte)last; + + derOut.WriteEncoded(Asn1Tags.BitString, result); + return; + } + } + + derOut.WriteEncoded(Asn1Tags.BitString, (byte)mPadBits, mData); } - protected override int Asn1GetHashCode() + protected override int Asn1GetHashCode() { - return padBits.GetHashCode() ^ Arrays.GetHashCode(data); + return mPadBits.GetHashCode() ^ Arrays.GetHashCode(mData); } protected override bool Asn1Equals( @@ -213,8 +221,8 @@ namespace Org.BouncyCastle.Asn1 if (other == null) return false; - return this.padBits == other.padBits - && Arrays.AreEqual(this.data, other.data); + return this.mPadBits == other.mPadBits + && Arrays.AreEqual(this.mData, other.mData); } public override string GetString() @@ -236,12 +244,23 @@ namespace Org.BouncyCastle.Asn1 internal static DerBitString FromAsn1Octets(byte[] octets) { if (octets.Length < 1) - throw new ArgumentException("truncated BIT STRING detected"); + throw new ArgumentException("truncated BIT STRING detected", "octets"); + + int padBits = octets[0]; + byte[] data = Arrays.CopyOfRange(octets, 1, octets.Length); + + if (padBits > 0 && padBits < 8 && data.Length > 0) + { + int last = data[data.Length - 1]; + int mask = (1 << padBits) - 1; + + if ((last & mask) != 0) + { + return new BerBitString(data, padBits); + } + } - int padBits = octets[0]; - byte[] data = new byte[octets.Length - 1]; - Array.Copy(octets, 1, data, 0, data.Length); - return new DerBitString(data, padBits); + return new DerBitString(data, padBits); } } } diff --git a/crypto/src/asn1/DerOutputStream.cs b/crypto/src/asn1/DerOutputStream.cs index c03d9dc11..69d5d5f28 100644 --- a/crypto/src/asn1/DerOutputStream.cs +++ b/crypto/src/asn1/DerOutputStream.cs @@ -19,7 +19,7 @@ namespace Org.BouncyCastle.Asn1 if (length > 127) { int size = 1; - uint val = (uint) length; + uint val = (uint)length; while ((val >>= 8) != 0) { @@ -43,18 +43,29 @@ namespace Org.BouncyCastle.Asn1 int tag, byte[] bytes) { - WriteByte((byte) tag); + WriteByte((byte)tag); WriteLength(bytes.Length); Write(bytes, 0, bytes.Length); } - internal void WriteEncoded( + internal void WriteEncoded( + int tag, + byte first, + byte[] bytes) + { + WriteByte((byte)tag); + WriteLength(bytes.Length + 1); + WriteByte(first); + Write(bytes, 0, bytes.Length); + } + + internal void WriteEncoded( int tag, byte[] bytes, int offset, int length) { - WriteByte((byte) tag); + WriteByte((byte)tag); WriteLength(length); Write(bytes, offset, length); } diff --git a/crypto/src/asn1/cmp/PKIFailureInfo.cs b/crypto/src/asn1/cmp/PKIFailureInfo.cs index 896bf0992..75a3ff0d7 100644 --- a/crypto/src/asn1/cmp/PKIFailureInfo.cs +++ b/crypto/src/asn1/cmp/PKIFailureInfo.cs @@ -77,15 +77,14 @@ namespace Org.BouncyCastle.Asn1.Cmp /** * Basic constructor. */ - public PkiFailureInfo( - int info) - : base(GetBytes(info), GetPadBits(info)) + public PkiFailureInfo(int info) + : base(info) { } public PkiFailureInfo( DerBitString info) - : base(info.GetBytes(), info.PadBits) + : base(info.GetBytes(), info.PadBits) { } diff --git a/crypto/src/asn1/misc/NetscapeCertType.cs b/crypto/src/asn1/misc/NetscapeCertType.cs index d5db6523d..d809eae66 100644 --- a/crypto/src/asn1/misc/NetscapeCertType.cs +++ b/crypto/src/asn1/misc/NetscapeCertType.cs @@ -36,7 +36,7 @@ namespace Org.BouncyCastle.Asn1.Misc * e.g. (X509NetscapeCertType.sslCA | X509NetscapeCertType.smimeCA) */ public NetscapeCertType(int usage) - : base(GetBytes(usage), GetPadBits(usage)) + : base(usage) { } diff --git a/crypto/src/asn1/ocsp/BasicOCSPResponse.cs b/crypto/src/asn1/ocsp/BasicOCSPResponse.cs index dd666addf..064335ae8 100644 --- a/crypto/src/asn1/ocsp/BasicOCSPResponse.cs +++ b/crypto/src/asn1/ocsp/BasicOCSPResponse.cs @@ -94,7 +94,12 @@ namespace Org.BouncyCastle.Asn1.Ocsp get { return signature; } } - [Obsolete("Use Certs property instead")] + public byte[] GetSignatureOctets() + { + return signature.GetOctets(); + } + + [Obsolete("Use Certs property instead")] public Asn1Sequence GetCerts() { return certs; diff --git a/crypto/src/asn1/ocsp/Signature.cs b/crypto/src/asn1/ocsp/Signature.cs index a07e7a709..df6f43332 100644 --- a/crypto/src/asn1/ocsp/Signature.cs +++ b/crypto/src/asn1/ocsp/Signature.cs @@ -80,7 +80,12 @@ namespace Org.BouncyCastle.Asn1.Ocsp get { return signatureValue; } } - public Asn1Sequence Certs + public byte[] GetSignatureOctets() + { + return signatureValue.GetOctets(); + } + + public Asn1Sequence Certs { get { return certs; } } diff --git a/crypto/src/asn1/pkcs/CertificationRequest.cs b/crypto/src/asn1/pkcs/CertificationRequest.cs index 32b1612d2..35bdd56eb 100644 --- a/crypto/src/asn1/pkcs/CertificationRequest.cs +++ b/crypto/src/asn1/pkcs/CertificationRequest.cs @@ -73,7 +73,12 @@ namespace Org.BouncyCastle.Asn1.Pkcs get { return sigBits; } } - public override Asn1Object ToAsn1Object() + public byte[] GetSignatureOctets() + { + return sigBits.GetOctets(); + } + + public override Asn1Object ToAsn1Object() { return new DerSequence(reqInfo, sigAlgId, sigBits); } diff --git a/crypto/src/asn1/x509/AttributeCertificate.cs b/crypto/src/asn1/x509/AttributeCertificate.cs index 5f85910da..41893b6b4 100644 --- a/crypto/src/asn1/x509/AttributeCertificate.cs +++ b/crypto/src/asn1/x509/AttributeCertificate.cs @@ -63,7 +63,12 @@ namespace Org.BouncyCastle.Asn1.X509 get { return signatureValue; } } - /** + public byte[] GetSignatureOctets() + { + return signatureValue.GetOctets(); + } + + /** * Produce an object suitable for an Asn1OutputStream. *
          *  AttributeCertificate ::= Sequence {
diff --git a/crypto/src/asn1/x509/CertificateList.cs b/crypto/src/asn1/x509/CertificateList.cs
index 0412e0816..567cf132a 100644
--- a/crypto/src/asn1/x509/CertificateList.cs
+++ b/crypto/src/asn1/x509/CertificateList.cs
@@ -80,7 +80,12 @@ namespace Org.BouncyCastle.Asn1.X509
 			get { return sig; }
 		}
 
-		public int Version
+        public byte[] GetSignatureOctets()
+        {
+            return sig.GetOctets();
+        }
+
+        public int Version
 		{
 			get { return tbsCertList.Version; }
 		}
diff --git a/crypto/src/asn1/x509/KeyUsage.cs b/crypto/src/asn1/x509/KeyUsage.cs
index fef04e8b9..aeaffb708 100644
--- a/crypto/src/asn1/x509/KeyUsage.cs
+++ b/crypto/src/asn1/x509/KeyUsage.cs
@@ -53,9 +53,8 @@ namespace Org.BouncyCastle.Asn1.X509
          * allowed uses for the key.
          * e.g. (KeyUsage.keyEncipherment | KeyUsage.dataEncipherment)
          */
-        public KeyUsage(
-			int usage)
-			: base(GetBytes(usage), GetPadBits(usage))
+        public KeyUsage(int usage)
+			: base(usage)
         {
         }
 
diff --git a/crypto/src/asn1/x509/ReasonFlags.cs b/crypto/src/asn1/x509/ReasonFlags.cs
index f204c36aa..ad45e84ae 100644
--- a/crypto/src/asn1/x509/ReasonFlags.cs
+++ b/crypto/src/asn1/x509/ReasonFlags.cs
@@ -31,13 +31,12 @@ namespace Org.BouncyCastle.Asn1.X509
          * @param reasons - the bitwise OR of the Key Reason flags giving the
          * allowed uses for the key.
          */
-        public ReasonFlags(
-            int reasons)
-             : base(GetBytes(reasons), GetPadBits(reasons))
+        public ReasonFlags(int reasons)
+             : base(reasons)
         {
         }
 
-		public ReasonFlags(
+        public ReasonFlags(
             DerBitString reasons)
              : base(reasons.GetBytes(), reasons.PadBits)
         {
diff --git a/crypto/src/asn1/x509/SubjectPublicKeyInfo.cs b/crypto/src/asn1/x509/SubjectPublicKeyInfo.cs
index 8ce4b2762..477329b7e 100644
--- a/crypto/src/asn1/x509/SubjectPublicKeyInfo.cs
+++ b/crypto/src/asn1/x509/SubjectPublicKeyInfo.cs
@@ -75,7 +75,7 @@ namespace Org.BouncyCastle.Asn1.X509
          */
         public Asn1Object GetPublicKey()
         {
-			return Asn1Object.FromByteArray(keyData.GetBytes());
+			return Asn1Object.FromByteArray(keyData.GetOctets());
         }
 
 		/**
diff --git a/crypto/src/asn1/x509/X509CertificateStructure.cs b/crypto/src/asn1/x509/X509CertificateStructure.cs
index c8558ae61..6e7c85de6 100644
--- a/crypto/src/asn1/x509/X509CertificateStructure.cs
+++ b/crypto/src/asn1/x509/X509CertificateStructure.cs
@@ -119,6 +119,11 @@ namespace Org.BouncyCastle.Asn1.X509
             get { return sig; }
         }
 
+        public byte[] GetSignatureOctets()
+        {
+            return sig.GetOctets();
+        }
+
         public override Asn1Object ToAsn1Object()
         {
             return new DerSequence(tbsCert, sigAlgID, sig);
diff --git a/crypto/src/math/BigInteger.cs b/crypto/src/math/BigInteger.cs
index 2ca3da978..794f252e8 100644
--- a/crypto/src/math/BigInteger.cs
+++ b/crypto/src/math/BigInteger.cs
@@ -964,7 +964,7 @@ namespace Org.BouncyCastle.Math
         //
         // BitLen(value) is the number of bits in value.
         //
-        private static int BitLen(int w)
+        internal static int BitLen(int w)
         {
             uint v = (uint)w;
             uint t = v >> 24;
diff --git a/crypto/src/ocsp/BasicOCSPResp.cs b/crypto/src/ocsp/BasicOCSPResp.cs
index 4253726bb..dec3b0bc5 100644
--- a/crypto/src/ocsp/BasicOCSPResp.cs
+++ b/crypto/src/ocsp/BasicOCSPResp.cs
@@ -111,7 +111,7 @@ namespace Org.BouncyCastle.Ocsp
 
 		public byte[] GetSignature()
 		{
-			return resp.Signature.GetBytes();
+			return resp.GetSignatureOctets();
 		}
 
 		private IList GetCertList()
diff --git a/crypto/src/ocsp/OCSPReq.cs b/crypto/src/ocsp/OCSPReq.cs
index 84808e50a..29e8cc015 100644
--- a/crypto/src/ocsp/OCSPReq.cs
+++ b/crypto/src/ocsp/OCSPReq.cs
@@ -153,10 +153,10 @@ namespace Org.BouncyCastle.Ocsp
 			if (!this.IsSigned)
 				return null;
 
-			return req.OptionalSignature.SignatureValue.GetBytes();
+			return req.OptionalSignature.GetSignatureOctets();
 		}
 
-		private IList GetCertList()
+        private IList GetCertList()
 		{
 			// load the certificates if we have any
 
diff --git a/crypto/src/pkcs/Pkcs10CertificationRequest.cs b/crypto/src/pkcs/Pkcs10CertificationRequest.cs
index 1789f2a70..633a57ebe 100644
--- a/crypto/src/pkcs/Pkcs10CertificationRequest.cs
+++ b/crypto/src/pkcs/Pkcs10CertificationRequest.cs
@@ -344,7 +344,7 @@ namespace Org.BouncyCastle.Pkcs
 
                 Platform.Dispose(streamCalculator.Stream);
 
-                return ((IVerifier)streamCalculator.GetResult()).IsVerified(sigBits.GetBytes());
+                return ((IVerifier)streamCalculator.GetResult()).IsVerified(sigBits.GetOctets());
             }
             catch (Exception e)
             {
diff --git a/crypto/src/tsp/TimeStampResponseGenerator.cs b/crypto/src/tsp/TimeStampResponseGenerator.cs
index 8d798de67..b596f8d97 100644
--- a/crypto/src/tsp/TimeStampResponseGenerator.cs
+++ b/crypto/src/tsp/TimeStampResponseGenerator.cs
@@ -166,9 +166,8 @@ namespace Org.BouncyCastle.Tsp
         class FailInfo
             : DerBitString
         {
-            internal FailInfo(
-                int failInfoValue)
-                : base(GetBytes(failInfoValue), GetPadBits(failInfoValue))
+            internal FailInfo(int failInfoValue)
+                : base(failInfoValue)
             {
             }
         }
diff --git a/crypto/src/x509/X509Certificate.cs b/crypto/src/x509/X509Certificate.cs
index fc7f96aa9..472ef7308 100644
--- a/crypto/src/x509/X509Certificate.cs
+++ b/crypto/src/x509/X509Certificate.cs
@@ -237,10 +237,10 @@ namespace Org.BouncyCastle.X509
 		/// A byte array containg the signature of the certificate.
 		public virtual byte[] GetSignature()
 		{
-			return c.Signature.GetBytes();
+			return c.GetSignatureOctets();
 		}
 
-		/// 
+        /// 
 		/// A meaningful version of the Signature Algorithm. (EG SHA1WITHRSA)
 		/// 
 		/// A sting representing the signature algorithm.
diff --git a/crypto/src/x509/X509Crl.cs b/crypto/src/x509/X509Crl.cs
index 53de3e91f..ee564dacb 100644
--- a/crypto/src/x509/X509Crl.cs
+++ b/crypto/src/x509/X509Crl.cs
@@ -211,7 +211,7 @@ namespace Org.BouncyCastle.X509
 
 		public virtual byte[] GetSignature()
 		{
-			return c.Signature.GetBytes();
+			return c.GetSignatureOctets();
 		}
 
 		public virtual string SigAlgName
diff --git a/crypto/src/x509/X509V2AttributeCertificate.cs b/crypto/src/x509/X509V2AttributeCertificate.cs
index 9376538a1..c41b31239 100644
--- a/crypto/src/x509/X509V2AttributeCertificate.cs
+++ b/crypto/src/x509/X509V2AttributeCertificate.cs
@@ -147,9 +147,14 @@ namespace Org.BouncyCastle.X509
 				throw new CertificateNotYetValidException("certificate not valid until " + NotBefore);
 		}
 
+        public virtual AlgorithmIdentifier SignatureAlgorithm
+        {
+            get { return cert.SignatureAlgorithm; }
+        }
+
 		public virtual byte[] GetSignature()
 		{
-			return cert.SignatureValue.GetBytes();
+            return cert.GetSignatureOctets();
 		}
 
         public virtual void Verify(
diff --git a/crypto/test/src/asn1/test/BitStringTest.cs b/crypto/test/src/asn1/test/BitStringTest.cs
index 3a2dc3156..fccaf8fa0 100644
--- a/crypto/test/src/asn1/test/BitStringTest.cs
+++ b/crypto/test/src/asn1/test/BitStringTest.cs
@@ -4,44 +4,132 @@ using System.IO;
 using NUnit.Framework;
 
 using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
 using Org.BouncyCastle.Utilities.Test;
 
 namespace Org.BouncyCastle.Asn1.Tests
 {
     [TestFixture]
     public class BitStringTest
-        : ITest
+        : SimpleTest
     {
-        public ITestResult Perform()
+        private void DoTestZeroLengthStrings()
+        {
+            // basic construction
+            DerBitString s1 = new DerBitString(new byte[0], 0);
+
+            s1.GetBytes();
+
+            if (!Arrays.AreEqual(s1.GetEncoded(), Hex.Decode("030100")))
+            {
+                Fail("zero encoding wrong");
+            }
+
+            try
+            {
+                new DerBitString(null, 1);
+                Fail("exception not thrown");
+            }
+            catch (ArgumentNullException e)
+            {
+                //if (!"data cannot be null".Equals(e.Message))
+                //{
+                //    Fail("Unexpected exception");
+                //}
+            }
+
+            try
+            {
+                new DerBitString(new byte[0], 1);
+                Fail("exception not thrown");
+            }
+            catch (ArgumentException e)
+            {
+                //if (!"zero length data with non-zero pad bits".Equals(e.Message))
+                //{
+                //    Fail("Unexpected exception");
+                //}
+            }
+
+            try
+            {
+                new DerBitString(new byte[1], 8);
+                Fail("exception not thrown");
+            }
+            catch (ArgumentException e)
+            {
+                //if (!"pad bits cannot be greater than 7 or less than 0".Equals(e.Message))
+                //{
+                //    Fail("Unexpected exception");
+                //}
+            }
+
+            DerBitString s2 = new DerBitString(0);
+            if (!Arrays.AreEqual(s1.GetEncoded(), s2.GetEncoded()))
+            {
+                Fail("zero encoding wrong");
+            }
+        }
+
+        private void DoTestRandomPadBits()
+        {
+            byte[] test = Hex.Decode("030206c0");
+
+            byte[] test1 = Hex.Decode("030206f0");
+            byte[] test2 = Hex.Decode("030206c1");
+            byte[] test3 = Hex.Decode("030206c7");
+            byte[] test4 = Hex.Decode("030206d1");
+
+            EncodingCheck(test, test1);
+            EncodingCheck(test, test2);
+            EncodingCheck(test, test3);
+            EncodingCheck(test, test4);
+        }
+
+        private void EncodingCheck(byte[] derData, byte[] dlData)
+        {
+            if (Arrays.AreEqual(derData, Asn1Object.FromByteArray(dlData).GetEncoded()))
+            {
+                //Fail("failed DL check");
+                Fail("failed BER check");
+            }
+            if (!Arrays.AreEqual(derData, Asn1Object.FromByteArray(dlData).GetDerEncoded()))
+            {
+                Fail("failed DER check");
+            }
+        }
+
+        public override void PerformTest()
         {
             KeyUsage k = new KeyUsage(KeyUsage.DigitalSignature);
             if ((k.GetBytes()[0] != (byte)KeyUsage.DigitalSignature) || (k.PadBits != 7))
             {
-                return new SimpleTestResult(false, Name + ": failed digitalSignature");
+                Fail("failed digitalSignature");
             }
 
             k = new KeyUsage(KeyUsage.NonRepudiation);
             if ((k.GetBytes()[0] != (byte)KeyUsage.NonRepudiation) || (k.PadBits != 6))
             {
-                return new SimpleTestResult(false, Name + ": failed nonRepudiation");
+                Fail("failed nonRepudiation");
             }
 
             k = new KeyUsage(KeyUsage.KeyEncipherment);
             if ((k.GetBytes()[0] != (byte)KeyUsage.KeyEncipherment) || (k.PadBits != 5))
             {
-                return new SimpleTestResult(false, Name + ": failed keyEncipherment");
+                Fail("failed keyEncipherment");
             }
 
             k = new KeyUsage(KeyUsage.CrlSign);
             if ((k.GetBytes()[0] != (byte)KeyUsage.CrlSign)  || (k.PadBits != 1))
             {
-                return new SimpleTestResult(false, Name + ": failed cRLSign");
+                Fail("failed cRLSign");
             }
 
             k = new KeyUsage(KeyUsage.DecipherOnly);
             if ((k.GetBytes()[1] != (byte)(KeyUsage.DecipherOnly >> 8))  || (k.PadBits != 7))
             {
-                return new SimpleTestResult(false, Name + ": failed decipherOnly");
+                Fail("failed decipherOnly");
             }
 
 			// test for zero length bit string
@@ -51,27 +139,25 @@ namespace Org.BouncyCastle.Asn1.Tests
 			}
 			catch (IOException e)
 			{
-				return new SimpleTestResult(false, Name + ": " + e);
+				Fail(e.ToString());
 			}
 
-            return new SimpleTestResult(true, Name + ": Okay");
+            DoTestRandomPadBits();
+            DoTestZeroLengthStrings();
         }
 
-        public string Name
+        public override string Name
         {
 			get { return "BitString"; }
         }
 
-		public static void Main(
+        public static void Main(
             string[] args)
         {
-            ITest test = new BitStringTest();
-            ITestResult result = test.Perform();
-
-			Console.WriteLine(result);
+            RunTest(new BitStringTest());
         }
 
-		[Test]
+        [Test]
         public void TestFunction()
         {
             string resultText = Perform().ToString();
diff --git a/crypto/test/src/crypto/tls/test/TlsTestClientImpl.cs b/crypto/test/src/crypto/tls/test/TlsTestClientImpl.cs
index 48af9e0f8..0cc1883ba 100644
--- a/crypto/test/src/crypto/tls/test/TlsTestClientImpl.cs
+++ b/crypto/test/src/crypto/tls/test/TlsTestClientImpl.cs
@@ -128,14 +128,14 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
             Asn1EncodableVector v = new Asn1EncodableVector();
             v.Add(cert.TbsCertificate);
             v.Add(cert.SignatureAlgorithm);
-            v.Add(CorruptBitString(cert.Signature));
+            v.Add(CorruptSignature(cert.Signature));
 
             return X509CertificateStructure.GetInstance(new DerSequence(v));
         }
 
-        protected virtual DerBitString CorruptBitString(DerBitString bs)
+        protected virtual DerBitString CorruptSignature(DerBitString bs)
         {
-            return new DerBitString(CorruptBit(bs.GetBytes()));
+            return new DerBitString(CorruptBit(bs.GetOctets()));
         }
 
         protected virtual byte[] CorruptBit(byte[] bs)
diff --git a/crypto/test/src/test/PKCS10CertRequestTest.cs b/crypto/test/src/test/PKCS10CertRequestTest.cs
index 819439cd8..ba62db32f 100644
--- a/crypto/test/src/test/PKCS10CertRequestTest.cs
+++ b/crypto/test/src/test/PKCS10CertRequestTest.cs
@@ -210,7 +210,7 @@ namespace Org.BouncyCastle.Tests
             byte[] b = req.GetCertificationRequestInfo().GetEncoded();
             sig.BlockUpdate(b, 0, b.Length);
 
-            if (!sig.VerifySignature(req.Signature.GetBytes()))
+            if (!sig.VerifySignature(req.GetSignatureOctets()))
             {
                 Fail("signature not mapped correctly.");
             }
@@ -264,7 +264,7 @@ namespace Org.BouncyCastle.Tests
             byte[] b = req.GetCertificationRequestInfo().GetEncoded();
             sig.BlockUpdate(b, 0, b.Length);
 
-            if (!sig.VerifySignature(req.Signature.GetBytes()))
+            if (!sig.VerifySignature(req.GetSignatureOctets()))
             {
                 Fail("signature not mapped correctly.");
             }
@@ -325,7 +325,7 @@ namespace Org.BouncyCastle.Tests
             byte[] encoded = req.GetCertificationRequestInfo().GetEncoded();
             sig.BlockUpdate(encoded, 0, encoded.Length);
 
-            if (!sig.VerifySignature(req.Signature.GetBytes()))
+            if (!sig.VerifySignature(req.GetSignatureOctets()))
             {
                 Fail("signature not mapped correctly.");
             }
-- 
cgit 1.5.1


From 218a170ece285fd49f82326c752a3d0fb31881dd Mon Sep 17 00:00:00 2001
From: Peter Dettman 
Date: Tue, 10 Nov 2015 19:42:21 +0700
Subject: Address various compiler warnings

---
 crypto/src/asn1/ess/OtherCertID.cs                     |  3 ++-
 crypto/src/asn1/pkcs/EncryptionScheme.cs               |  2 +-
 crypto/src/cms/CMSAuthenticatedData.cs                 |  2 +-
 crypto/src/cms/CMSAuthenticatedDataParser.cs           |  2 +-
 crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs  |  2 +-
 crypto/src/cms/CMSEnvelopedData.cs                     |  2 +-
 crypto/src/cms/CMSEnvelopedDataParser.cs               |  2 +-
 crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs      |  2 +-
 crypto/src/cms/CMSEnvelopedHelper.cs                   | 12 ++++++------
 crypto/src/cms/CMSPBEKey.cs                            |  4 ++--
 crypto/src/cms/CMSSignedData.cs                        |  2 +-
 crypto/src/cms/CMSSignedDataParser.cs                  |  4 ++--
 crypto/src/cms/CMSSignedDataStreamGenerator.cs         |  2 +-
 crypto/src/cms/CMSSignedHelper.cs                      |  2 +-
 crypto/src/cms/KEKRecipientInfoGenerator.cs            |  2 +-
 crypto/src/cms/KEKRecipientInformation.cs              |  2 +-
 crypto/src/cms/KeyAgreeRecipientInfoGenerator.cs       |  2 +-
 crypto/src/cms/KeyAgreeRecipientInformation.cs         |  2 +-
 crypto/src/cms/KeyTransRecipientInfoGenerator.cs       |  2 +-
 crypto/src/cms/KeyTransRecipientInformation.cs         |  2 +-
 crypto/src/cms/RecipientInformation.cs                 |  6 +++---
 crypto/src/cms/SignerInformation.cs                    | 16 ++++++++--------
 crypto/src/crypto/operators/Asn1Signature.cs           |  8 ++++----
 crypto/src/ocsp/BasicOCSPResp.cs                       |  4 ++--
 crypto/src/ocsp/CertificateID.cs                       |  4 ++--
 crypto/src/ocsp/OCSPReq.cs                             |  2 +-
 crypto/src/openssl/MiscPemGenerator.cs                 |  2 +-
 crypto/src/pkcs/Pkcs10CertificationRequest.cs          |  6 +++---
 crypto/src/pkcs/Pkcs12Store.cs                         | 10 +++++-----
 crypto/src/pkcs/Pkcs12Utilities.cs                     |  4 ++--
 crypto/src/pkcs/PrivateKeyInfoFactory.cs               |  2 +-
 crypto/src/pkix/PkixCertPathValidator.cs               |  4 ++--
 crypto/src/security/PbeUtilities.cs                    | 12 ++++++------
 crypto/src/security/PrivateKeyFactory.cs               |  2 +-
 crypto/src/security/PublicKeyFactory.cs                |  2 +-
 crypto/src/tsp/TimeStampRequest.cs                     |  2 +-
 crypto/src/tsp/TimeStampToken.cs                       |  4 ++--
 crypto/src/tsp/TimeStampTokenInfo.cs                   |  2 +-
 crypto/src/x509/AttributeCertificateHolder.cs          |  4 ++--
 crypto/src/x509/X509Certificate.cs                     |  6 +++---
 crypto/src/x509/X509Crl.cs                             |  2 +-
 crypto/src/x509/X509SignatureUtil.cs                   |  8 ++++----
 crypto/test/src/asn1/test/BitStringTest.cs             | 18 +++---------------
 crypto/test/src/asn1/test/LDSSecurityObjectUnitTest.cs |  3 ++-
 crypto/test/src/crypto/test/Pkcs5Test.cs               |  2 +-
 crypto/test/src/pkcs/test/PKCS12StoreTest.cs           |  4 ++--
 crypto/test/src/test/CertTest.cs                       |  2 +-
 crypto/test/src/test/PKCS10CertRequestTest.cs          |  6 +++---
 48 files changed, 96 insertions(+), 106 deletions(-)

(limited to 'crypto/test/src')

diff --git a/crypto/src/asn1/ess/OtherCertID.cs b/crypto/src/asn1/ess/OtherCertID.cs
index 972ef8c6b..3d221b0ec 100644
--- a/crypto/src/asn1/ess/OtherCertID.cs
+++ b/crypto/src/asn1/ess/OtherCertID.cs
@@ -1,5 +1,6 @@
 using System;
 
+using Org.BouncyCastle.Asn1.Oiw;
 using Org.BouncyCastle.Asn1.X509;
 
 namespace Org.BouncyCastle.Asn1.Ess
@@ -78,7 +79,7 @@ namespace Org.BouncyCastle.Asn1.Ess
 				if (otherCertHash.ToAsn1Object() is Asn1OctetString)
 				{
 					// SHA-1
-					return new AlgorithmIdentifier("1.3.14.3.2.26");
+					return new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1);
 				}
 
 				return DigestInfo.GetInstance(otherCertHash).AlgorithmID;
diff --git a/crypto/src/asn1/pkcs/EncryptionScheme.cs b/crypto/src/asn1/pkcs/EncryptionScheme.cs
index 5b64d6f67..ff9103d12 100644
--- a/crypto/src/asn1/pkcs/EncryptionScheme.cs
+++ b/crypto/src/asn1/pkcs/EncryptionScheme.cs
@@ -43,7 +43,7 @@ namespace Org.BouncyCastle.Asn1.Pkcs
 
 		public override Asn1Object ToAsn1Object()
         {
-			return new DerSequence(ObjectID, Parameters);
+            return new DerSequence(Algorithm, Parameters);
         }
     }
 }
diff --git a/crypto/src/cms/CMSAuthenticatedData.cs b/crypto/src/cms/CMSAuthenticatedData.cs
index 5e234da2b..33b4cc22c 100644
--- a/crypto/src/cms/CMSAuthenticatedData.cs
+++ b/crypto/src/cms/CMSAuthenticatedData.cs
@@ -83,7 +83,7 @@ namespace Org.BouncyCastle.Cms
 		*/
 		public string MacAlgOid
 		{
-			get { return macAlg.ObjectID.Id; }
+            get { return macAlg.Algorithm.Id; }
 		}
 
 		/**
diff --git a/crypto/src/cms/CMSAuthenticatedDataParser.cs b/crypto/src/cms/CMSAuthenticatedDataParser.cs
index c99aac61c..7defafc07 100644
--- a/crypto/src/cms/CMSAuthenticatedDataParser.cs
+++ b/crypto/src/cms/CMSAuthenticatedDataParser.cs
@@ -111,7 +111,7 @@ namespace Org.BouncyCastle.Cms
 		*/
 		public string MacAlgOid
 		{
-			get { return macAlg.ObjectID.Id; }
+            get { return macAlg.Algorithm.Id; }
 		}
 
 
diff --git a/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs b/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs
index a135cdd11..4d18d10d4 100644
--- a/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs
+++ b/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs
@@ -165,7 +165,7 @@ namespace Org.BouncyCastle.Cms
 				Stream octetOutputStream = CmsUtilities.CreateBerOctetOutputStream(
 					eiGen.GetRawOutputStream(), 0, false, _bufferSize);
 
-				IMac mac = MacUtilities.GetMac(macAlgId.ObjectID);
+                IMac mac = MacUtilities.GetMac(macAlgId.Algorithm);
 				// TODO Confirm no ParametersWithRandom needed
 	            mac.Init(cipherParameters);
 				Stream mOut = new TeeOutputStream(octetOutputStream, new MacOutputStream(mac));
diff --git a/crypto/src/cms/CMSEnvelopedData.cs b/crypto/src/cms/CMSEnvelopedData.cs
index 0731c307e..223d0ca73 100644
--- a/crypto/src/cms/CMSEnvelopedData.cs
+++ b/crypto/src/cms/CMSEnvelopedData.cs
@@ -73,7 +73,7 @@ namespace Org.BouncyCastle.Cms
         */
         public string EncryptionAlgOid
         {
-			get { return encAlg.ObjectID.Id; }
+            get { return encAlg.Algorithm.Id; }
         }
 
 		/**
diff --git a/crypto/src/cms/CMSEnvelopedDataParser.cs b/crypto/src/cms/CMSEnvelopedDataParser.cs
index 01a949d47..d5dfaf53d 100644
--- a/crypto/src/cms/CMSEnvelopedDataParser.cs
+++ b/crypto/src/cms/CMSEnvelopedDataParser.cs
@@ -101,7 +101,7 @@ namespace Org.BouncyCastle.Cms
 		 */
 		public string EncryptionAlgOid
 		{
-			get { return _encAlg.ObjectID.Id; }
+            get { return _encAlg.Algorithm.Id; }
 		}
 
 		/**
diff --git a/crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs b/crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs
index bde8d9926..8e6d2729b 100644
--- a/crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs
+++ b/crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs
@@ -166,7 +166,7 @@ namespace Org.BouncyCastle.Cms
 				Stream octetOutputStream = CmsUtilities.CreateBerOctetOutputStream(
 					eiGen.GetRawOutputStream(), 0, false, _bufferSize);
 
-				IBufferedCipher cipher = CipherUtilities.GetCipher(encAlgID.ObjectID);
+                IBufferedCipher cipher = CipherUtilities.GetCipher(encAlgID.Algorithm);
 				cipher.Init(true, new ParametersWithRandom(cipherParameters, rand));
 				CipherStream cOut = new CipherStream(octetOutputStream, null, cipher);
 
diff --git a/crypto/src/cms/CMSEnvelopedHelper.cs b/crypto/src/cms/CMSEnvelopedHelper.cs
index fe2b14cd9..77d2da47a 100644
--- a/crypto/src/cms/CMSEnvelopedHelper.cs
+++ b/crypto/src/cms/CMSEnvelopedHelper.cs
@@ -160,7 +160,7 @@ namespace Org.BouncyCastle.Cms
 
 			public CmsReadable GetReadable(KeyParameter sKey)
 			{
-				string macAlg = this.algorithm.ObjectID.Id;
+                string macAlg = this.algorithm.Algorithm.Id;
 //				Asn1Object sParams = this.algorithm.Parameters.ToAsn1Object();
 
 				try
@@ -190,11 +190,11 @@ namespace Org.BouncyCastle.Cms
 //						if (asn1Params != null && !(asn1Params is Asn1Null))
 //						{
 //							cipherParameters = ParameterUtilities.GetCipherParameters(
-//							macAlg.ObjectID, cipherParameters, asn1Params);
+//							macAlg.Algorithm, cipherParameters, asn1Params);
 //						}
 //						else
 //						{
-//							string alg = macAlg.ObjectID.Id;
+//							string alg = macAlg.Algorithm.Id;
 //							if (alg.Equals(CmsEnvelopedDataGenerator.DesEde3Cbc)
 //								|| alg.Equals(CmsEnvelopedDataGenerator.IdeaCbc)
 //								|| alg.Equals(CmsEnvelopedDataGenerator.Cast5Cbc))
@@ -258,7 +258,7 @@ namespace Org.BouncyCastle.Cms
 			{
 				try
 				{
-					this.cipher =  CipherUtilities.GetCipher(this.algorithm.ObjectID);
+                    this.cipher = CipherUtilities.GetCipher(this.algorithm.Algorithm);
 
 					Asn1Encodable asn1Enc = this.algorithm.Parameters;
 					Asn1Object asn1Params = asn1Enc == null ? null : asn1Enc.ToAsn1Object();
@@ -268,11 +268,11 @@ namespace Org.BouncyCastle.Cms
 					if (asn1Params != null && !(asn1Params is Asn1Null))
 					{
 						cipherParameters = ParameterUtilities.GetCipherParameters(
-							this.algorithm.ObjectID, cipherParameters, asn1Params);
+                            this.algorithm.Algorithm, cipherParameters, asn1Params);
 					}
 					else
 					{
-						string alg = this.algorithm.ObjectID.Id;
+                        string alg = this.algorithm.Algorithm.Id;
 						if (alg.Equals(CmsEnvelopedDataGenerator.DesEde3Cbc)
 							|| alg.Equals(CmsEnvelopedDataGenerator.IdeaCbc)
 							|| alg.Equals(CmsEnvelopedDataGenerator.Cast5Cbc))
diff --git a/crypto/src/cms/CMSPBEKey.cs b/crypto/src/cms/CMSPBEKey.cs
index cb1e54c36..e03307e57 100644
--- a/crypto/src/cms/CMSPBEKey.cs
+++ b/crypto/src/cms/CMSPBEKey.cs
@@ -50,9 +50,9 @@ namespace Org.BouncyCastle.Cms
 			char[]				password,
 			AlgorithmIdentifier keyDerivationAlgorithm)
 		{
-			if (!keyDerivationAlgorithm.ObjectID.Equals(PkcsObjectIdentifiers.IdPbkdf2))
+            if (!keyDerivationAlgorithm.Algorithm.Equals(PkcsObjectIdentifiers.IdPbkdf2))
 				throw new ArgumentException("Unsupported key derivation algorithm: "
-					+ keyDerivationAlgorithm.ObjectID);
+                    + keyDerivationAlgorithm.Algorithm);
 
 			Pbkdf2Params kdfParams = Pbkdf2Params.GetInstance(
 				keyDerivationAlgorithm.Parameters.ToAsn1Object());
diff --git a/crypto/src/cms/CMSSignedData.cs b/crypto/src/cms/CMSSignedData.cs
index 81c87a426..237c1528e 100644
--- a/crypto/src/cms/CMSSignedData.cs
+++ b/crypto/src/cms/CMSSignedData.cs
@@ -172,7 +172,7 @@ namespace Org.BouncyCastle.Cms
 					}
 					else
 					{
-						byte[] hash = (byte[]) hashes[info.DigestAlgorithm.ObjectID.Id];
+                        byte[] hash = (byte[])hashes[info.DigestAlgorithm.Algorithm.Id];
 
 						signerInfos.Add(new SignerInformation(info, contentType, null, new BaseDigestCalculator(hash)));
 					}
diff --git a/crypto/src/cms/CMSSignedDataParser.cs b/crypto/src/cms/CMSSignedDataParser.cs
index e5e6edc58..fb51ab119 100644
--- a/crypto/src/cms/CMSSignedDataParser.cs
+++ b/crypto/src/cms/CMSSignedDataParser.cs
@@ -122,7 +122,7 @@ namespace Org.BouncyCastle.Cms
 
 					try
 					{
-						string digestOid = id.ObjectID.Id;
+                        string digestOid = id.Algorithm.Id;
 						string digestName = Helper.GetDigestAlgName(digestOid);
 
 						if (!this._digests.Contains(digestName))
@@ -216,7 +216,7 @@ namespace Org.BouncyCastle.Cms
 					{
 						SignerInfo info = SignerInfo.GetInstance(o.ToAsn1Object());
 						string digestName = Helper.GetDigestAlgName(
-							info.DigestAlgorithm.ObjectID.Id);
+                            info.DigestAlgorithm.Algorithm.Id);
 
 						byte[] hash = (byte[]) hashes[digestName];
 
diff --git a/crypto/src/cms/CMSSignedDataStreamGenerator.cs b/crypto/src/cms/CMSSignedDataStreamGenerator.cs
index 1477d884f..d0ab7428a 100644
--- a/crypto/src/cms/CMSSignedDataStreamGenerator.cs
+++ b/crypto/src/cms/CMSSignedDataStreamGenerator.cs
@@ -459,7 +459,7 @@ namespace Org.BouncyCastle.Cms
 			// NB: Would need to call FixAlgID on the DigestAlgorithmID
 
 			// For precalculated signers, just need to register the algorithm, not configure a digest
-			RegisterDigestOid(si.DigestAlgorithmID.ObjectID.Id);
+            RegisterDigestOid(si.DigestAlgorithmID.Algorithm.Id);
 		}
 
 		/**
diff --git a/crypto/src/cms/CMSSignedHelper.cs b/crypto/src/cms/CMSSignedHelper.cs
index 23657ef86..5b6c93b6a 100644
--- a/crypto/src/cms/CMSSignedHelper.cs
+++ b/crypto/src/cms/CMSSignedHelper.cs
@@ -348,7 +348,7 @@ namespace Org.BouncyCastle.Cms
 			AlgorithmIdentifier algId)
 		{
 			if (algId.Parameters == null)
-				return new AlgorithmIdentifier(algId.ObjectID, DerNull.Instance);
+                return new AlgorithmIdentifier(algId.Algorithm, DerNull.Instance);
 
 			return algId;
 		}
diff --git a/crypto/src/cms/KEKRecipientInfoGenerator.cs b/crypto/src/cms/KEKRecipientInfoGenerator.cs
index a9bedade6..c66f27547 100644
--- a/crypto/src/cms/KEKRecipientInfoGenerator.cs
+++ b/crypto/src/cms/KEKRecipientInfoGenerator.cs
@@ -52,7 +52,7 @@ namespace Org.BouncyCastle.Cms
 		{
 			byte[] keyBytes = contentEncryptionKey.GetKey();
 
-			IWrapper keyWrapper = Helper.CreateWrapper(keyEncryptionAlgorithm.ObjectID.Id);
+            IWrapper keyWrapper = Helper.CreateWrapper(keyEncryptionAlgorithm.Algorithm.Id);
 			keyWrapper.Init(true, new ParametersWithRandom(keyEncryptionKey, random));
         	Asn1OctetString encryptedKey = new DerOctetString(
 				keyWrapper.Wrap(keyBytes, 0, keyBytes.Length));
diff --git a/crypto/src/cms/KEKRecipientInformation.cs b/crypto/src/cms/KEKRecipientInformation.cs
index f960197d6..871dc76d4 100644
--- a/crypto/src/cms/KEKRecipientInformation.cs
+++ b/crypto/src/cms/KEKRecipientInformation.cs
@@ -40,7 +40,7 @@ namespace Org.BouncyCastle.Cms
 			try
 			{
 				byte[] encryptedKey = info.EncryptedKey.GetOctets();
-				IWrapper keyWrapper = WrapperUtilities.GetWrapper(keyEncAlg.ObjectID.Id);
+                IWrapper keyWrapper = WrapperUtilities.GetWrapper(keyEncAlg.Algorithm.Id);
 
 				keyWrapper.Init(false, key);
 
diff --git a/crypto/src/cms/KeyAgreeRecipientInfoGenerator.cs b/crypto/src/cms/KeyAgreeRecipientInfoGenerator.cs
index 4fafb7c6e..6bd2cea91 100644
--- a/crypto/src/cms/KeyAgreeRecipientInfoGenerator.cs
+++ b/crypto/src/cms/KeyAgreeRecipientInfoGenerator.cs
@@ -164,7 +164,7 @@ namespace Org.BouncyCastle.Cms
 		{
 			SubjectPublicKeyInfo spki = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey);
 			return new OriginatorPublicKey(
-				new AlgorithmIdentifier(spki.AlgorithmID.ObjectID, DerNull.Instance),
+                new AlgorithmIdentifier(spki.AlgorithmID.Algorithm, DerNull.Instance),
 				spki.PublicKeyData.GetBytes());
 		}
 	}
diff --git a/crypto/src/cms/KeyAgreeRecipientInformation.cs b/crypto/src/cms/KeyAgreeRecipientInformation.cs
index 8e006e545..73e57a76a 100644
--- a/crypto/src/cms/KeyAgreeRecipientInformation.cs
+++ b/crypto/src/cms/KeyAgreeRecipientInformation.cs
@@ -130,7 +130,7 @@ namespace Org.BouncyCastle.Cms
             AsymmetricKeyParameter	senderPublicKey,
             AsymmetricKeyParameter	receiverPrivateKey)
         {
-            DerObjectIdentifier agreeAlgID = keyEncAlg.ObjectID;
+            DerObjectIdentifier agreeAlgID = keyEncAlg.Algorithm;
 
             ICipherParameters senderPublicParams = senderPublicKey;
             ICipherParameters receiverPrivateParams = receiverPrivateKey;
diff --git a/crypto/src/cms/KeyTransRecipientInfoGenerator.cs b/crypto/src/cms/KeyTransRecipientInfoGenerator.cs
index 0992e6da6..a1d8fbfa8 100644
--- a/crypto/src/cms/KeyTransRecipientInfoGenerator.cs
+++ b/crypto/src/cms/KeyTransRecipientInfoGenerator.cs
@@ -64,7 +64,7 @@ namespace Org.BouncyCastle.Cms
 			byte[] keyBytes = contentEncryptionKey.GetKey();
 			AlgorithmIdentifier keyEncryptionAlgorithm = info.AlgorithmID;
 
-			IWrapper keyWrapper = Helper.CreateWrapper(keyEncryptionAlgorithm.ObjectID.Id);
+            IWrapper keyWrapper = Helper.CreateWrapper(keyEncryptionAlgorithm.Algorithm.Id);
 			keyWrapper.Init(true, new ParametersWithRandom(recipientPublicKey, random));
 			byte[] encryptedKeyBytes = keyWrapper.Wrap(keyBytes, 0, keyBytes.Length);
 
diff --git a/crypto/src/cms/KeyTransRecipientInformation.cs b/crypto/src/cms/KeyTransRecipientInformation.cs
index 24121cb2c..3b1ea7b5e 100644
--- a/crypto/src/cms/KeyTransRecipientInformation.cs
+++ b/crypto/src/cms/KeyTransRecipientInformation.cs
@@ -68,7 +68,7 @@ namespace Org.BouncyCastle.Cms
 		internal KeyParameter UnwrapKey(ICipherParameters key)
 		{
 			byte[] encryptedKey = info.EncryptedKey.GetOctets();
-			string keyExchangeAlgorithm = GetExchangeEncryptionAlgorithmName(keyEncAlg.ObjectID);
+            string keyExchangeAlgorithm = GetExchangeEncryptionAlgorithmName(keyEncAlg.Algorithm);
 
 			try
 			{
diff --git a/crypto/src/cms/RecipientInformation.cs b/crypto/src/cms/RecipientInformation.cs
index 8b0316be4..272b841f2 100644
--- a/crypto/src/cms/RecipientInformation.cs
+++ b/crypto/src/cms/RecipientInformation.cs
@@ -33,8 +33,8 @@ namespace Org.BouncyCastle.Cms
 		internal string GetContentAlgorithmName()
 		{
 			AlgorithmIdentifier algorithm = secureReadable.Algorithm;
-//			return CmsEnvelopedHelper.Instance.GetSymmetricCipherName(algorithm.ObjectID.Id);
-			return algorithm.ObjectID.Id;
+//			return CmsEnvelopedHelper.Instance.GetSymmetricCipherName(algorithm.Algorithm.Id);
+			return algorithm.Algorithm.Id;
 		}
 
 		public RecipientID RecipientID
@@ -54,7 +54,7 @@ namespace Org.BouncyCastle.Cms
         */
         public string KeyEncryptionAlgOid
         {
-			get { return keyEncAlg.ObjectID.Id; }
+            get { return keyEncAlg.Algorithm.Id; }
         }
 
 		/**
diff --git a/crypto/src/cms/SignerInformation.cs b/crypto/src/cms/SignerInformation.cs
index 581286a3f..dad128263 100644
--- a/crypto/src/cms/SignerInformation.cs
+++ b/crypto/src/cms/SignerInformation.cs
@@ -117,7 +117,7 @@ namespace Org.BouncyCastle.Cms
 		*/
 		public string DigestAlgOid
 		{
-			get { return digestAlgorithm.ObjectID.Id; }
+            get { return digestAlgorithm.Algorithm.Id; }
 		}
 
 		/**
@@ -156,7 +156,7 @@ namespace Org.BouncyCastle.Cms
 		*/
 		public string EncryptionAlgOid
 		{
-			get { return encryptionAlgorithm.ObjectID.Id; }
+            get { return encryptionAlgorithm.Algorithm.Id; }
 		}
 
 		/**
@@ -272,7 +272,7 @@ namespace Org.BouncyCastle.Cms
 					*/
 					SignerInfo si = SignerInfo.GetInstance(asn1Obj.ToAsn1Object());
 
-					string digestName = CmsSignedHelper.Instance.GetDigestAlgName(si.DigestAlgorithm.ObjectID.Id);
+                    string digestName = CmsSignedHelper.Instance.GetDigestAlgName(si.DigestAlgorithm.Algorithm.Id);
 
 					counterSignatures.Add(new SignerInformation(si, null, null, new CounterSignatureDigestCalculator(digestName, GetSignature())));
 				}
@@ -298,7 +298,7 @@ namespace Org.BouncyCastle.Cms
 			string digestName = Helper.GetDigestAlgName(this.DigestAlgOid);
 			IDigest digest = Helper.GetDigestInstance(digestName);
 
-			DerObjectIdentifier sigAlgOid = this.encryptionAlgorithm.ObjectID;
+            DerObjectIdentifier sigAlgOid = this.encryptionAlgorithm.Algorithm;
 			Asn1Encodable sigParams = this.encryptionAlgorithm.Parameters;
 			ISigner sig;
 
@@ -318,12 +318,12 @@ namespace Org.BouncyCastle.Cms
 					Asn1.Pkcs.RsassaPssParameters pss = Asn1.Pkcs.RsassaPssParameters.GetInstance(
 						sigParams.ToAsn1Object());
 
-					if (!pss.HashAlgorithm.ObjectID.Equals(this.digestAlgorithm.ObjectID))
+                    if (!pss.HashAlgorithm.Algorithm.Equals(this.digestAlgorithm.Algorithm))
 						throw new CmsException("RSASSA-PSS signature parameters specified incorrect hash algorithm");
-					if (!pss.MaskGenAlgorithm.ObjectID.Equals(Asn1.Pkcs.PkcsObjectIdentifiers.IdMgf1))
+                    if (!pss.MaskGenAlgorithm.Algorithm.Equals(Asn1.Pkcs.PkcsObjectIdentifiers.IdMgf1))
 						throw new CmsException("RSASSA-PSS signature parameters specified unknown MGF");
 
-					IDigest pssDigest = DigestUtilities.GetDigest(pss.HashAlgorithm.ObjectID);
+                    IDigest pssDigest = DigestUtilities.GetDigest(pss.HashAlgorithm.Algorithm);
 					int saltLength = pss.SaltLength.Value.IntValue;
 					byte trailerField = (byte) pss.TrailerField.Value.IntValue;
 
@@ -532,7 +532,7 @@ namespace Org.BouncyCastle.Cms
 
 					DigestInfo digInfo = DerDecode(decrypt);
 
-					if (!digInfo.AlgorithmID.ObjectID.Equals(digestAlgorithm.ObjectID))
+                    if (!digInfo.AlgorithmID.Algorithm.Equals(digestAlgorithm.Algorithm))
 					{
 						return false;
 					}
diff --git a/crypto/src/crypto/operators/Asn1Signature.cs b/crypto/src/crypto/operators/Asn1Signature.cs
index 3a20e4bff..e023c1d18 100644
--- a/crypto/src/crypto/operators/Asn1Signature.cs
+++ b/crypto/src/crypto/operators/Asn1Signature.cs
@@ -170,13 +170,13 @@ namespace Org.BouncyCastle.Crypto.Operators
 
             if (parameters != null && !derNull.Equals(parameters))
             {
-                if (sigAlgId.ObjectID.Equals(PkcsObjectIdentifiers.IdRsassaPss))
+                if (sigAlgId.Algorithm.Equals(PkcsObjectIdentifiers.IdRsassaPss))
                 {
                     RsassaPssParameters rsaParams = RsassaPssParameters.GetInstance(parameters);
 
-                    return GetDigestAlgName(rsaParams.HashAlgorithm.ObjectID) + "withRSAandMGF1";
+                    return GetDigestAlgName(rsaParams.HashAlgorithm.Algorithm) + "withRSAandMGF1";
                 }
-                if (sigAlgId.ObjectID.Equals(X9ObjectIdentifiers.ECDsaWithSha2))
+                if (sigAlgId.Algorithm.Equals(X9ObjectIdentifiers.ECDsaWithSha2))
                 {
                     Asn1Sequence ecDsaParams = Asn1Sequence.GetInstance(parameters);
 
@@ -184,7 +184,7 @@ namespace Org.BouncyCastle.Crypto.Operators
                 }
             }
 
-            return sigAlgId.ObjectID.Id;
+            return sigAlgId.Algorithm.Id;
         }
 
         private static RsassaPssParameters CreatePssParams(
diff --git a/crypto/src/ocsp/BasicOCSPResp.cs b/crypto/src/ocsp/BasicOCSPResp.cs
index dec3b0bc5..63ab8921e 100644
--- a/crypto/src/ocsp/BasicOCSPResp.cs
+++ b/crypto/src/ocsp/BasicOCSPResp.cs
@@ -95,12 +95,12 @@ namespace Org.BouncyCastle.Ocsp
 
 		public string SignatureAlgName
 		{
-			get { return OcspUtilities.GetAlgorithmName(resp.SignatureAlgorithm.ObjectID); }
+            get { return OcspUtilities.GetAlgorithmName(resp.SignatureAlgorithm.Algorithm); }
 		}
 
 		public string SignatureAlgOid
 		{
-			get { return resp.SignatureAlgorithm.ObjectID.Id; }
+            get { return resp.SignatureAlgorithm.Algorithm.Id; }
 		}
 
 		[Obsolete("RespData class is no longer required as all functionality is available on this class")]
diff --git a/crypto/src/ocsp/CertificateID.cs b/crypto/src/ocsp/CertificateID.cs
index a8f035759..ec902d5c3 100644
--- a/crypto/src/ocsp/CertificateID.cs
+++ b/crypto/src/ocsp/CertificateID.cs
@@ -43,7 +43,7 @@ namespace Org.BouncyCastle.Ocsp
 
 		public string HashAlgOid
 		{
-			get { return id.HashAlgorithm.ObjectID.Id; }
+            get { return id.HashAlgorithm.Algorithm.Id; }
 		}
 
 		public byte[] GetIssuerNameHash()
@@ -118,7 +118,7 @@ namespace Org.BouncyCastle.Ocsp
 		{
 			try
 			{
-				String hashAlgorithm = hashAlg.ObjectID.Id;
+                String hashAlgorithm = hashAlg.Algorithm.Id;
 
 				X509Name issuerName = PrincipalUtilities.GetSubjectX509Principal(issuerCert);
 				byte[] issuerNameHash = DigestUtilities.CalculateDigest(
diff --git a/crypto/src/ocsp/OCSPReq.cs b/crypto/src/ocsp/OCSPReq.cs
index 29e8cc015..0cd95c6d6 100644
--- a/crypto/src/ocsp/OCSPReq.cs
+++ b/crypto/src/ocsp/OCSPReq.cs
@@ -144,7 +144,7 @@ namespace Org.BouncyCastle.Ocsp
 				if (!this.IsSigned)
 					return null;
 
-				return req.OptionalSignature.SignatureAlgorithm.ObjectID.Id;
+                return req.OptionalSignature.SignatureAlgorithm.Algorithm.Id;
 			}
 		}
 
diff --git a/crypto/src/openssl/MiscPemGenerator.cs b/crypto/src/openssl/MiscPemGenerator.cs
index 6b91e8b1c..568465fe4 100644
--- a/crypto/src/openssl/MiscPemGenerator.cs
+++ b/crypto/src/openssl/MiscPemGenerator.cs
@@ -218,7 +218,7 @@ namespace Org.BouncyCastle.OpenSsl
         {
             PrivateKeyInfo info = PrivateKeyInfoFactory.CreatePrivateKeyInfo(akp);
             AlgorithmIdentifier algID = info.PrivateKeyAlgorithm;
-            DerObjectIdentifier oid = algID.ObjectID;
+            DerObjectIdentifier oid = algID.Algorithm;
 
             if (oid.Equals(X9ObjectIdentifiers.IdDsa))
             {
diff --git a/crypto/src/pkcs/Pkcs10CertificationRequest.cs b/crypto/src/pkcs/Pkcs10CertificationRequest.cs
index 633a57ebe..0411d9190 100644
--- a/crypto/src/pkcs/Pkcs10CertificationRequest.cs
+++ b/crypto/src/pkcs/Pkcs10CertificationRequest.cs
@@ -402,14 +402,14 @@ namespace Org.BouncyCastle.Pkcs
 
 			if (asn1Params != null && !(asn1Params is Asn1Null))
 			{
-				if (sigAlgId.ObjectID.Equals(PkcsObjectIdentifiers.IdRsassaPss))
+                if (sigAlgId.Algorithm.Equals(PkcsObjectIdentifiers.IdRsassaPss))
 				{
 					RsassaPssParameters rsaParams = RsassaPssParameters.GetInstance(asn1Params);
-					return GetDigestAlgName(rsaParams.HashAlgorithm.ObjectID) + "withRSAandMGF1";
+                    return GetDigestAlgName(rsaParams.HashAlgorithm.Algorithm) + "withRSAandMGF1";
 				}
 			}
 
-			return sigAlgId.ObjectID.Id;
+            return sigAlgId.Algorithm.Id;
 		}
 
 		private static string GetDigestAlgName(
diff --git a/crypto/src/pkcs/Pkcs12Store.cs b/crypto/src/pkcs/Pkcs12Store.cs
index e4fe29401..b649a726e 100644
--- a/crypto/src/pkcs/Pkcs12Store.cs
+++ b/crypto/src/pkcs/Pkcs12Store.cs
@@ -213,7 +213,7 @@ namespace Org.BouncyCastle.Pkcs
 
                 byte[] data = ((Asn1OctetString) info.Content).GetOctets();
 
-                byte[] mac = CalculatePbeMac(algId.ObjectID, salt, itCount, password, false, data);
+                byte[] mac = CalculatePbeMac(algId.Algorithm, salt, itCount, password, false, data);
                 byte[] dig = dInfo.GetDigest();
 
                 if (!Arrays.ConstantTimeAreEqual(mac, dig))
@@ -222,7 +222,7 @@ namespace Org.BouncyCastle.Pkcs
                         throw new IOException("PKCS12 key store MAC invalid - wrong password or corrupted file.");
 
                     // Try with incorrect zero length password
-                    mac = CalculatePbeMac(algId.ObjectID, salt, itCount, password, true, data);
+                    mac = CalculatePbeMac(algId.Algorithm, salt, itCount, password, true, data);
 
                     if (!Arrays.ConstantTimeAreEqual(mac, dig))
                         throw new IOException("PKCS12 key store MAC invalid - wrong password or corrupted file.");
@@ -1015,14 +1015,14 @@ namespace Org.BouncyCastle.Pkcs
             bool				wrongPkcs12Zero,
             byte[]				data)
         {
-            IBufferedCipher cipher = PbeUtilities.CreateEngine(algId.ObjectID) as IBufferedCipher;
+            IBufferedCipher cipher = PbeUtilities.CreateEngine(algId.Algorithm) as IBufferedCipher;
 
             if (cipher == null)
-                throw new Exception("Unknown encryption algorithm: " + algId.ObjectID);
+                throw new Exception("Unknown encryption algorithm: " + algId.Algorithm);
 
             Pkcs12PbeParams pbeParameters = Pkcs12PbeParams.GetInstance(algId.Parameters);
             ICipherParameters cipherParams = PbeUtilities.GenerateCipherParameters(
-                algId.ObjectID, password, wrongPkcs12Zero, pbeParameters);
+                algId.Algorithm, password, wrongPkcs12Zero, pbeParameters);
             cipher.Init(forEncryption, cipherParams);
             return cipher.DoFinal(data);
         }
diff --git a/crypto/src/pkcs/Pkcs12Utilities.cs b/crypto/src/pkcs/Pkcs12Utilities.cs
index d35c8b6a2..923eca5a5 100644
--- a/crypto/src/pkcs/Pkcs12Utilities.cs
+++ b/crypto/src/pkcs/Pkcs12Utilities.cs
@@ -56,10 +56,10 @@ namespace Org.BouncyCastle.Pkcs
 				int itCount = mData.IterationCount.IntValue;
 				byte[] data = Asn1OctetString.GetInstance(info.Content).GetOctets();
 				byte[] res = Pkcs12Store.CalculatePbeMac(
-					mData.Mac.AlgorithmID.ObjectID, mData.GetSalt(), itCount, passwd, false, data);
+                    mData.Mac.AlgorithmID.Algorithm, mData.GetSalt(), itCount, passwd, false, data);
 
 				AlgorithmIdentifier algId = new AlgorithmIdentifier(
-					mData.Mac.AlgorithmID.ObjectID, DerNull.Instance);
+                    mData.Mac.AlgorithmID.Algorithm, DerNull.Instance);
 				DigestInfo dInfo = new DigestInfo(algId, res);
 
 				mData = new MacData(dInfo, mData.GetSalt(), itCount);
diff --git a/crypto/src/pkcs/PrivateKeyInfoFactory.cs b/crypto/src/pkcs/PrivateKeyInfoFactory.cs
index 723d50f08..c6aab4884 100644
--- a/crypto/src/pkcs/PrivateKeyInfoFactory.cs
+++ b/crypto/src/pkcs/PrivateKeyInfoFactory.cs
@@ -195,7 +195,7 @@ namespace Org.BouncyCastle.Pkcs
 
             IBufferedCipher cipher = PbeUtilities.CreateEngine(algID) as IBufferedCipher;
             if (cipher == null)
-                throw new Exception("Unknown encryption algorithm: " + algID.ObjectID);
+                throw new Exception("Unknown encryption algorithm: " + algID.Algorithm);
 
             ICipherParameters cipherParameters = PbeUtilities.GenerateCipherParameters(
                 algID, passPhrase, wrongPkcs12Zero);
diff --git a/crypto/src/pkix/PkixCertPathValidator.cs b/crypto/src/pkix/PkixCertPathValidator.cs
index 7eb838886..fcfa63837 100644
--- a/crypto/src/pkix/PkixCertPathValidator.cs
+++ b/crypto/src/pkix/PkixCertPathValidator.cs
@@ -204,7 +204,7 @@ namespace Org.BouncyCastle.Pkix
                         "Algorithm identifier of public key of trust anchor could not be read.", e, certPath, -1);
             }
 
-//			DerObjectIdentifier workingPublicKeyAlgorithm = workingAlgId.ObjectID;
+//			DerObjectIdentifier workingPublicKeyAlgorithm = workingAlgId.Algorithm;
 //			Asn1Encodable workingPublicKeyParameters = workingAlgId.Parameters;
 
             //
@@ -358,7 +358,7 @@ namespace Org.BouncyCastle.Pkix
 
                     workingAlgId = PkixCertPathValidatorUtilities.GetAlgorithmIdentifier(workingPublicKey);
                     // (f)
-//                    workingPublicKeyAlgorithm = workingAlgId.ObjectID;
+//                    workingPublicKeyAlgorithm = workingAlgId.Algorithm;
                     // (e)
 //                    workingPublicKeyParameters = workingAlgId.Parameters;
                 }
diff --git a/crypto/src/security/PbeUtilities.cs b/crypto/src/security/PbeUtilities.cs
index 56d68ba0a..0cb235ae6 100644
--- a/crypto/src/security/PbeUtilities.cs
+++ b/crypto/src/security/PbeUtilities.cs
@@ -345,7 +345,7 @@ namespace Org.BouncyCastle.Security
             AlgorithmIdentifier algID,
             char[]              password)
         {
-            return GenerateCipherParameters(algID.ObjectID.Id, password, false, algID.Parameters);
+            return GenerateCipherParameters(algID.Algorithm.Id, password, false, algID.Parameters);
         }
 
         public static ICipherParameters GenerateCipherParameters(
@@ -353,7 +353,7 @@ namespace Org.BouncyCastle.Security
             char[]              password,
             bool				wrongPkcs12Zero)
         {
-            return GenerateCipherParameters(algID.ObjectID.Id, password, wrongPkcs12Zero, algID.Parameters);
+            return GenerateCipherParameters(algID.Algorithm.Id, password, wrongPkcs12Zero, algID.Parameters);
         }
 
         public static ICipherParameters GenerateCipherParameters(
@@ -401,10 +401,10 @@ namespace Org.BouncyCastle.Security
             {
                 PbeS2Parameters s2p = PbeS2Parameters.GetInstance(pbeParameters.ToAsn1Object());
                 AlgorithmIdentifier encScheme = s2p.EncryptionScheme;
-                DerObjectIdentifier encOid = encScheme.ObjectID;
+                DerObjectIdentifier encOid = encScheme.Algorithm;
                 Asn1Object encParams = encScheme.Parameters.ToAsn1Object();
 
-                // TODO What about s2p.KeyDerivationFunc.ObjectID?
+                // TODO What about s2p.KeyDerivationFunc.Algorithm?
                 Pbkdf2Params pbeParams = Pbkdf2Params.GetInstance(s2p.KeyDerivationFunc.Parameters.ToAsn1Object());
 
                 byte[] iv;
@@ -577,13 +577,13 @@ namespace Org.BouncyCastle.Security
         public static object CreateEngine(
             AlgorithmIdentifier algID)
         {
-            string algorithm = algID.ObjectID.Id;
+            string algorithm = algID.Algorithm.Id;
 
             if (IsPkcs5Scheme2(algorithm))
             {
                 PbeS2Parameters s2p = PbeS2Parameters.GetInstance(algID.Parameters.ToAsn1Object());
                 AlgorithmIdentifier encScheme = s2p.EncryptionScheme;
-                return CipherUtilities.GetCipher(encScheme.ObjectID);
+                return CipherUtilities.GetCipher(encScheme.Algorithm);
             }
 
             return CreateEngine(algorithm);
diff --git a/crypto/src/security/PrivateKeyFactory.cs b/crypto/src/security/PrivateKeyFactory.cs
index edc5ef85a..b9538b33d 100644
--- a/crypto/src/security/PrivateKeyFactory.cs
+++ b/crypto/src/security/PrivateKeyFactory.cs
@@ -45,7 +45,7 @@ namespace Org.BouncyCastle.Security
             PrivateKeyInfo keyInfo)
         {
             AlgorithmIdentifier algID = keyInfo.PrivateKeyAlgorithm;
-            DerObjectIdentifier algOid = algID.ObjectID;
+            DerObjectIdentifier algOid = algID.Algorithm;
 
             // TODO See RSAUtil.isRsaOid in Java build
             if (algOid.Equals(PkcsObjectIdentifiers.RsaEncryption)
diff --git a/crypto/src/security/PublicKeyFactory.cs b/crypto/src/security/PublicKeyFactory.cs
index 8c0be4f70..f1b28b774 100644
--- a/crypto/src/security/PublicKeyFactory.cs
+++ b/crypto/src/security/PublicKeyFactory.cs
@@ -44,7 +44,7 @@ namespace Org.BouncyCastle.Security
             SubjectPublicKeyInfo keyInfo)
         {
             AlgorithmIdentifier algID = keyInfo.AlgorithmID;
-            DerObjectIdentifier algOid = algID.ObjectID;
+            DerObjectIdentifier algOid = algID.Algorithm;
 
             // TODO See RSAUtil.isRsaOid in Java build
             if (algOid.Equals(PkcsObjectIdentifiers.RsaEncryption)
diff --git a/crypto/src/tsp/TimeStampRequest.cs b/crypto/src/tsp/TimeStampRequest.cs
index 6b9699379..f54d33e04 100644
--- a/crypto/src/tsp/TimeStampRequest.cs
+++ b/crypto/src/tsp/TimeStampRequest.cs
@@ -77,7 +77,7 @@ namespace Org.BouncyCastle.Tsp
 
 		public string MessageImprintAlgOid
 		{
-			get { return req.MessageImprint.HashAlgorithm.ObjectID.Id; }
+            get { return req.MessageImprint.HashAlgorithm.Algorithm.Id; }
 		}
 
 		public byte[] GetMessageImprintDigest()
diff --git a/crypto/src/tsp/TimeStampToken.cs b/crypto/src/tsp/TimeStampToken.cs
index 51a9592dc..105208a7d 100644
--- a/crypto/src/tsp/TimeStampToken.cs
+++ b/crypto/src/tsp/TimeStampToken.cs
@@ -271,10 +271,10 @@ namespace Org.BouncyCastle.Tsp
 				if (certID != null)
 					return "SHA-1";
 
-				if (NistObjectIdentifiers.IdSha256.Equals(certIDv2.HashAlgorithm.ObjectID))
+                if (NistObjectIdentifiers.IdSha256.Equals(certIDv2.HashAlgorithm.Algorithm))
 					return "SHA-256";
 
-				return certIDv2.HashAlgorithm.ObjectID.Id;
+                return certIDv2.HashAlgorithm.Algorithm.Id;
 			}
 
 			public AlgorithmIdentifier GetHashAlgorithm()
diff --git a/crypto/src/tsp/TimeStampTokenInfo.cs b/crypto/src/tsp/TimeStampTokenInfo.cs
index 5027a87c4..cdef826bc 100644
--- a/crypto/src/tsp/TimeStampTokenInfo.cs
+++ b/crypto/src/tsp/TimeStampTokenInfo.cs
@@ -86,7 +86,7 @@ namespace Org.BouncyCastle.Tsp
 
 		public string MessageImprintAlgOid
 		{
-			get { return tstInfo.MessageImprint.HashAlgorithm.ObjectID.Id; }
+            get { return tstInfo.MessageImprint.HashAlgorithm.Algorithm.Id; }
 		}
 
 		public byte[] GetMessageImprintDigest()
diff --git a/crypto/src/x509/AttributeCertificateHolder.cs b/crypto/src/x509/AttributeCertificateHolder.cs
index 3a6af4c20..04460cd59 100644
--- a/crypto/src/x509/AttributeCertificateHolder.cs
+++ b/crypto/src/x509/AttributeCertificateHolder.cs
@@ -103,7 +103,7 @@ namespace Org.BouncyCastle.X509
 			// TODO Allow 'objectDigest' to be null?
 
 			holder = new Holder(new ObjectDigestInfo(digestedObjectType, otherObjectTypeID,
-				new AlgorithmIdentifier(digestAlgorithm), Arrays.Clone(objectDigest)));
+				new AlgorithmIdentifier(new DerObjectIdentifier(digestAlgorithm)), Arrays.Clone(objectDigest)));
 		}
 
 		/**
@@ -147,7 +147,7 @@ namespace Org.BouncyCastle.X509
 
 				return odi == null
 					?	null
-					:	odi.DigestAlgorithm.ObjectID.Id;
+					:	odi.DigestAlgorithm.Algorithm.Id;
 			}
 		}
 
diff --git a/crypto/src/x509/X509Certificate.cs b/crypto/src/x509/X509Certificate.cs
index 472ef7308..6d7bd7a61 100644
--- a/crypto/src/x509/X509Certificate.cs
+++ b/crypto/src/x509/X509Certificate.cs
@@ -246,7 +246,7 @@ namespace Org.BouncyCastle.X509
 		/// A sting representing the signature algorithm.
 		public virtual string SigAlgName
 		{
-			get { return SignerUtilities.GetEncodingName(c.SignatureAlgorithm.ObjectID); }
+            get { return SignerUtilities.GetEncodingName(c.SignatureAlgorithm.Algorithm); }
 		}
 
 		/// 
@@ -255,7 +255,7 @@ namespace Org.BouncyCastle.X509
 		/// A string containg a '.' separated object id.
 		public virtual string SigAlgOid
 		{
-			get { return c.SignatureAlgorithm.ObjectID.Id; }
+            get { return c.SignatureAlgorithm.Algorithm.Id; }
 		}
 
 		/// 
@@ -586,7 +586,7 @@ namespace Org.BouncyCastle.X509
 
 		private static bool IsAlgIDEqual(AlgorithmIdentifier id1, AlgorithmIdentifier id2)
 		{
-			if (!id1.ObjectID.Equals(id2.ObjectID))
+            if (!id1.Algorithm.Equals(id2.Algorithm))
 				return false;
 
 			Asn1Encodable p1 = id1.Parameters;
diff --git a/crypto/src/x509/X509Crl.cs b/crypto/src/x509/X509Crl.cs
index ee564dacb..ecfb14132 100644
--- a/crypto/src/x509/X509Crl.cs
+++ b/crypto/src/x509/X509Crl.cs
@@ -221,7 +221,7 @@ namespace Org.BouncyCastle.X509
 
 		public virtual string SigAlgOid
 		{
-			get { return c.SignatureAlgorithm.ObjectID.Id; }
+            get { return c.SignatureAlgorithm.Algorithm.Id; }
 		}
 
 		public virtual byte[] GetSigAlgParams()
diff --git a/crypto/src/x509/X509SignatureUtil.cs b/crypto/src/x509/X509SignatureUtil.cs
index 7a4ab1448..858b8f446 100644
--- a/crypto/src/x509/X509SignatureUtil.cs
+++ b/crypto/src/x509/X509SignatureUtil.cs
@@ -55,13 +55,13 @@ namespace Org.BouncyCastle.X509
 
 			if (parameters != null && !derNull.Equals(parameters))
 			{
-				if (sigAlgId.ObjectID.Equals(PkcsObjectIdentifiers.IdRsassaPss))
+                if (sigAlgId.Algorithm.Equals(PkcsObjectIdentifiers.IdRsassaPss))
 				{
 					RsassaPssParameters rsaParams = RsassaPssParameters.GetInstance(parameters);
 
-					return GetDigestAlgName(rsaParams.HashAlgorithm.ObjectID) + "withRSAandMGF1";
+                    return GetDigestAlgName(rsaParams.HashAlgorithm.Algorithm) + "withRSAandMGF1";
 				}
-				if (sigAlgId.ObjectID.Equals(X9ObjectIdentifiers.ECDsaWithSha2))
+                if (sigAlgId.Algorithm.Equals(X9ObjectIdentifiers.ECDsaWithSha2))
 				{
 					Asn1Sequence ecDsaParams = Asn1Sequence.GetInstance(parameters);
 
@@ -69,7 +69,7 @@ namespace Org.BouncyCastle.X509
 				}
 			}
 
-			return sigAlgId.ObjectID.Id;
+            return sigAlgId.Algorithm.Id;
 		}
 
 		/**
diff --git a/crypto/test/src/asn1/test/BitStringTest.cs b/crypto/test/src/asn1/test/BitStringTest.cs
index fccaf8fa0..05be45941 100644
--- a/crypto/test/src/asn1/test/BitStringTest.cs
+++ b/crypto/test/src/asn1/test/BitStringTest.cs
@@ -31,12 +31,8 @@ namespace Org.BouncyCastle.Asn1.Tests
                 new DerBitString(null, 1);
                 Fail("exception not thrown");
             }
-            catch (ArgumentNullException e)
+            catch (ArgumentNullException)
             {
-                //if (!"data cannot be null".Equals(e.Message))
-                //{
-                //    Fail("Unexpected exception");
-                //}
             }
 
             try
@@ -44,12 +40,8 @@ namespace Org.BouncyCastle.Asn1.Tests
                 new DerBitString(new byte[0], 1);
                 Fail("exception not thrown");
             }
-            catch (ArgumentException e)
+            catch (ArgumentException)
             {
-                //if (!"zero length data with non-zero pad bits".Equals(e.Message))
-                //{
-                //    Fail("Unexpected exception");
-                //}
             }
 
             try
@@ -57,12 +49,8 @@ namespace Org.BouncyCastle.Asn1.Tests
                 new DerBitString(new byte[1], 8);
                 Fail("exception not thrown");
             }
-            catch (ArgumentException e)
+            catch (ArgumentException)
             {
-                //if (!"pad bits cannot be greater than 7 or less than 0".Equals(e.Message))
-                //{
-                //    Fail("Unexpected exception");
-                //}
             }
 
             DerBitString s2 = new DerBitString(0);
diff --git a/crypto/test/src/asn1/test/LDSSecurityObjectUnitTest.cs b/crypto/test/src/asn1/test/LDSSecurityObjectUnitTest.cs
index 042781632..914eda0b8 100644
--- a/crypto/test/src/asn1/test/LDSSecurityObjectUnitTest.cs
+++ b/crypto/test/src/asn1/test/LDSSecurityObjectUnitTest.cs
@@ -4,6 +4,7 @@ using NUnit.Framework;
 
 using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.Icao;
+using Org.BouncyCastle.Asn1.Oiw;
 using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Utilities.Test;
@@ -29,7 +30,7 @@ namespace Org.BouncyCastle.Asn1.Tests
 
         public override void PerformTest()
         {
-            AlgorithmIdentifier  algoId = new AlgorithmIdentifier("1.3.14.3.2.26");
+            AlgorithmIdentifier  algoId = new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1);
             DataGroupHash[] datas = new DataGroupHash[2];
 
             datas[0] = new DataGroupHash(1, new DerOctetString(GenerateHash()));
diff --git a/crypto/test/src/crypto/test/Pkcs5Test.cs b/crypto/test/src/crypto/test/Pkcs5Test.cs
index 8066e8e41..fdf1e7a66 100644
--- a/crypto/test/src/crypto/test/Pkcs5Test.cs
+++ b/crypto/test/src/crypto/test/Pkcs5Test.cs
@@ -115,7 +115,7 @@ namespace Org.BouncyCastle.Crypto.Tests
 
                 generator.Init(PbeParametersGenerator.Pkcs5PasswordToBytes(password), salt, iterationCount);
 
-                DerObjectIdentifier algOid = scheme.ObjectID;
+                DerObjectIdentifier algOid = scheme.Algorithm;
 
                 byte[] iv;
                 if (algOid.Equals(PkcsObjectIdentifiers.RC2Cbc))
diff --git a/crypto/test/src/pkcs/test/PKCS12StoreTest.cs b/crypto/test/src/pkcs/test/PKCS12StoreTest.cs
index c6b39135e..cd9dfcfad 100644
--- a/crypto/test/src/pkcs/test/PKCS12StoreTest.cs
+++ b/crypto/test/src/pkcs/test/PKCS12StoreTest.cs
@@ -837,7 +837,7 @@ namespace Org.BouncyCastle.Pkcs.Tests
 			EncryptedPrivateKeyInfo encInfo = EncryptedPrivateKeyInfo.GetInstance(sb.BagValue);
 
 			// check the key encryption
-			if (!encInfo.EncryptionAlgorithm.ObjectID.Equals(keyAlgorithm))
+            if (!encInfo.EncryptionAlgorithm.Algorithm.Equals(keyAlgorithm))
 			{
 				Fail("key encryption algorithm wrong");
 			}
@@ -845,7 +845,7 @@ namespace Org.BouncyCastle.Pkcs.Tests
 			// check the certificate encryption
 			EncryptedData cb = EncryptedData.GetInstance(c2.Content);
 
-			if (!cb.EncryptionAlgorithm.ObjectID.Equals(certAlgorithm))
+            if (!cb.EncryptionAlgorithm.Algorithm.Equals(certAlgorithm))
 			{
 				Fail("cert encryption algorithm wrong");
 			}
diff --git a/crypto/test/src/test/CertTest.cs b/crypto/test/src/test/CertTest.cs
index 9bb4df7d1..72e17e458 100644
--- a/crypto/test/src/test/CertTest.cs
+++ b/crypto/test/src/test/CertTest.cs
@@ -2452,7 +2452,7 @@ namespace Org.BouncyCastle.Tests
 
             DerSequence seq = new DerSequence(
                 tbsCertificate,
-                new AlgorithmIdentifier(sig.ObjectID),
+                new AlgorithmIdentifier(sig.Algorithm),
                 certStruct.Signature);
 
             try
diff --git a/crypto/test/src/test/PKCS10CertRequestTest.cs b/crypto/test/src/test/PKCS10CertRequestTest.cs
index ba62db32f..9bad0a678 100644
--- a/crypto/test/src/test/PKCS10CertRequestTest.cs
+++ b/crypto/test/src/test/PKCS10CertRequestTest.cs
@@ -193,7 +193,7 @@ namespace Org.BouncyCastle.Tests
                 Fail("Failed Verify check EC uncompressed encoded.");
             }
 
-            if (!req.SignatureAlgorithm.ObjectID.Equals(algOid))
+            if (!req.SignatureAlgorithm.Algorithm.Equals(algOid))
             {
                 Fail("ECDSA oid incorrect.");
             }
@@ -247,7 +247,7 @@ namespace Org.BouncyCastle.Tests
                 Fail("Failed Verify check EC encoded.");
             }
 
-            if (!req.SignatureAlgorithm.ObjectID.Equals(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001))
+            if (!req.SignatureAlgorithm.Algorithm.Equals(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001))
             {
                 Fail("ECGOST oid incorrect.");
             }
@@ -308,7 +308,7 @@ namespace Org.BouncyCastle.Tests
                 Fail("Failed verify check PSS encoded.");
             }
 
-            if (!req.SignatureAlgorithm.ObjectID.Equals(PkcsObjectIdentifiers.IdRsassaPss))
+            if (!req.SignatureAlgorithm.Algorithm.Equals(PkcsObjectIdentifiers.IdRsassaPss))
             {
                 Fail("PSS oid incorrect.");
             }
-- 
cgit 1.5.1


From 005288002936b16dce66912f06fcd1ba09ed2508 Mon Sep 17 00:00:00 2001
From: Peter Dettman 
Date: Thu, 12 Nov 2015 17:32:38 +0700
Subject: Use culture-independent prefix-check in MacUtilities.GetMac

- Fix for https://github.com/bcgit/bc-csharp/pull/40 (modified from original patch)
---
 crypto/Contributors.html                     |  6 +++--
 crypto/crypto.csproj                         |  5 ++++
 crypto/src/security/MacUtilities.cs          |  4 ++-
 crypto/test/src/security/test/TestMacUtil.cs | 38 ++++++++++++++++++++++++++++
 4 files changed, 50 insertions(+), 3 deletions(-)
 create mode 100644 crypto/test/src/security/test/TestMacUtil.cs

(limited to 'crypto/test/src')

diff --git a/crypto/Contributors.html b/crypto/Contributors.html
index 8908b857a..5211b193f 100644
--- a/crypto/Contributors.html
+++ b/crypto/Contributors.html
@@ -136,8 +136,10 @@
                 

John Allberg <john@ayoy.se> - improvements to Portable Class Library patch.

  • -

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

    +

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

    +
  • +
  • +

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

  • diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index 3f942800c..28d0b19b3 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -12114,6 +12114,11 @@ SubType = "Code" BuildAction = "Compile" /> + Date: Fri, 13 Nov 2015 13:34:13 +0700 Subject: Include basic encode/parse test --- crypto/test/src/asn1/test/BitStringTest.cs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'crypto/test/src') diff --git a/crypto/test/src/asn1/test/BitStringTest.cs b/crypto/test/src/asn1/test/BitStringTest.cs index 05be45941..f2ae3de97 100644 --- a/crypto/test/src/asn1/test/BitStringTest.cs +++ b/crypto/test/src/asn1/test/BitStringTest.cs @@ -19,8 +19,12 @@ namespace Org.BouncyCastle.Asn1.Tests // basic construction DerBitString s1 = new DerBitString(new byte[0], 0); + // check GetBytes() s1.GetBytes(); + // check encoding/decoding + DerBitString derBit = (DerBitString)Asn1Object.FromByteArray(s1.GetEncoded()); + if (!Arrays.AreEqual(s1.GetEncoded(), Hex.Decode("030100"))) { Fail("zero encoding wrong"); -- cgit 1.5.1 From 938f65781f98d1581caa75e0ba34dd42a475974d Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 13 Nov 2015 22:15:48 +0700 Subject: Update ECPrivateKeyStructure following Java API --- crypto/src/asn1/pkcs/PrivateKeyInfo.cs | 4 +- crypto/src/asn1/sec/ECPrivateKeyStructure.cs | 58 ++++++++++++++++++++++++++++ crypto/src/openssl/PEMReader.cs | 2 +- crypto/src/pkcs/PrivateKeyInfoFactory.cs | 33 +++++++--------- crypto/src/security/PrivateKeyFactory.cs | 15 ++++--- crypto/test/src/asn1/test/X9Test.cs | 22 ++++++----- 6 files changed, 96 insertions(+), 38 deletions(-) (limited to 'crypto/test/src') diff --git a/crypto/src/asn1/pkcs/PrivateKeyInfo.cs b/crypto/src/asn1/pkcs/PrivateKeyInfo.cs index 404277ba6..c5be7a315 100644 --- a/crypto/src/asn1/pkcs/PrivateKeyInfo.cs +++ b/crypto/src/asn1/pkcs/PrivateKeyInfo.cs @@ -29,14 +29,14 @@ namespace Org.BouncyCastle.Asn1.Pkcs return new PrivateKeyInfo(Asn1Sequence.GetInstance(obj)); } - public PrivateKeyInfo(AlgorithmIdentifier algID, Asn1Object privateKey) + public PrivateKeyInfo(AlgorithmIdentifier algID, Asn1Encodable privateKey) : this(algID, privateKey, null) { } public PrivateKeyInfo( AlgorithmIdentifier algID, - Asn1Object privateKey, + Asn1Encodable privateKey, Asn1Set attributes) { this.algID = algID; diff --git a/crypto/src/asn1/sec/ECPrivateKeyStructure.cs b/crypto/src/asn1/sec/ECPrivateKeyStructure.cs index 8d805fa30..32e020c0b 100644 --- a/crypto/src/asn1/sec/ECPrivateKeyStructure.cs +++ b/crypto/src/asn1/sec/ECPrivateKeyStructure.cs @@ -23,6 +23,7 @@ namespace Org.BouncyCastle.Asn1.Sec return new ECPrivateKeyStructure(Asn1Sequence.GetInstance(obj)); } + [Obsolete("Use 'GetInstance' instead")] public ECPrivateKeyStructure( Asn1Sequence seq) { @@ -32,6 +33,7 @@ namespace Org.BouncyCastle.Asn1.Sec this.seq = seq; } + [Obsolete("Use constructor which takes 'orderBitLength' instead, to guarantee correct encoding")] public ECPrivateKeyStructure( BigInteger key) { @@ -43,6 +45,23 @@ namespace Org.BouncyCastle.Asn1.Sec new DerOctetString(key.ToByteArrayUnsigned())); } + public ECPrivateKeyStructure( + int orderBitLength, + BigInteger key) + { + if (key == null) + throw new ArgumentNullException("key"); + if (orderBitLength < key.BitLength) + throw new ArgumentException("must be >= key bitlength", "orderBitLength"); + + byte[] bytes = BigIntegers.AsUnsignedByteArray((orderBitLength + 7) / 8, key); + + this.seq = new DerSequence( + new DerInteger(1), + new DerOctetString(bytes)); + } + + [Obsolete("Use constructor which takes 'orderBitLength' instead, to guarantee correct encoding")] public ECPrivateKeyStructure( BigInteger key, Asn1Encodable parameters) @@ -50,6 +69,7 @@ namespace Org.BouncyCastle.Asn1.Sec { } + [Obsolete("Use constructor which takes 'orderBitLength' instead, to guarantee correct encoding")] public ECPrivateKeyStructure( BigInteger key, DerBitString publicKey, @@ -75,6 +95,44 @@ namespace Org.BouncyCastle.Asn1.Sec this.seq = new DerSequence(v); } + public ECPrivateKeyStructure( + int orderBitLength, + BigInteger key, + Asn1Encodable parameters) + : this(orderBitLength, key, null, parameters) + { + } + + public ECPrivateKeyStructure( + int orderBitLength, + BigInteger key, + DerBitString publicKey, + Asn1Encodable parameters) + { + if (key == null) + throw new ArgumentNullException("key"); + if (orderBitLength < key.BitLength) + throw new ArgumentException("must be >= key bitlength", "orderBitLength"); + + byte[] bytes = BigIntegers.AsUnsignedByteArray((orderBitLength + 7) / 8, key); + + Asn1EncodableVector v = new Asn1EncodableVector( + new DerInteger(1), + new DerOctetString(bytes)); + + if (parameters != null) + { + v.Add(new DerTaggedObject(true, 0, parameters)); + } + + if (publicKey != null) + { + v.Add(new DerTaggedObject(true, 1, publicKey)); + } + + this.seq = new DerSequence(v); + } + public virtual BigInteger GetKey() { Asn1OctetString octs = (Asn1OctetString) seq[1]; diff --git a/crypto/src/openssl/PEMReader.cs b/crypto/src/openssl/PEMReader.cs index 987f4471c..9a5f99b1a 100644 --- a/crypto/src/openssl/PEMReader.cs +++ b/crypto/src/openssl/PEMReader.cs @@ -311,7 +311,7 @@ namespace Org.BouncyCastle.OpenSsl case "EC": { - ECPrivateKeyStructure pKey = new ECPrivateKeyStructure(seq); + ECPrivateKeyStructure pKey = ECPrivateKeyStructure.GetInstance(seq); AlgorithmIdentifier algId = new AlgorithmIdentifier( X9ObjectIdentifiers.IdECPublicKey, pKey.GetParameters()); diff --git a/crypto/src/pkcs/PrivateKeyInfoFactory.cs b/crypto/src/pkcs/PrivateKeyInfoFactory.cs index c6aab4884..aafc4c292 100644 --- a/crypto/src/pkcs/PrivateKeyInfoFactory.cs +++ b/crypto/src/pkcs/PrivateKeyInfoFactory.cs @@ -106,49 +106,46 @@ namespace Org.BouncyCastle.Pkcs if (key is ECPrivateKeyParameters) { - ECPrivateKeyParameters _key = (ECPrivateKeyParameters)key; + ECPrivateKeyParameters priv = (ECPrivateKeyParameters)key; + ECDomainParameters dp = priv.Parameters; + int orderBitLength = dp.N.BitLength; + AlgorithmIdentifier algID; ECPrivateKeyStructure ec; - if (_key.AlgorithmName == "ECGOST3410") + if (priv.AlgorithmName == "ECGOST3410") { - if (_key.PublicKeyParamSet == null) + if (priv.PublicKeyParamSet == null) throw Platform.CreateNotImplementedException("Not a CryptoPro parameter set"); Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters( - _key.PublicKeyParamSet, CryptoProObjectIdentifiers.GostR3411x94CryptoProParamSet); + priv.PublicKeyParamSet, CryptoProObjectIdentifiers.GostR3411x94CryptoProParamSet); - algID = new AlgorithmIdentifier( - CryptoProObjectIdentifiers.GostR3410x2001, - gostParams.ToAsn1Object()); + algID = new AlgorithmIdentifier(CryptoProObjectIdentifiers.GostR3410x2001, gostParams); // TODO Do we need to pass any parameters here? - ec = new ECPrivateKeyStructure(_key.D); + ec = new ECPrivateKeyStructure(orderBitLength, priv.D); } else { X962Parameters x962; - if (_key.PublicKeyParamSet == null) + if (priv.PublicKeyParamSet == null) { - ECDomainParameters kp = _key.Parameters; - X9ECParameters ecP = new X9ECParameters(kp.Curve, kp.G, kp.N, kp.H, kp.GetSeed()); - + X9ECParameters ecP = new X9ECParameters(dp.Curve, dp.G, dp.N, dp.H, dp.GetSeed()); x962 = new X962Parameters(ecP); } else { - x962 = new X962Parameters(_key.PublicKeyParamSet); + x962 = new X962Parameters(priv.PublicKeyParamSet); } - Asn1Object x962Object = x962.ToAsn1Object(); - // TODO Possible to pass the publicKey bitstring here? - ec = new ECPrivateKeyStructure(_key.D, x962Object); + ec = new ECPrivateKeyStructure(orderBitLength, priv.D, x962); - algID = new AlgorithmIdentifier(X9ObjectIdentifiers.IdECPublicKey, x962Object); + algID = new AlgorithmIdentifier(X9ObjectIdentifiers.IdECPublicKey, x962); } - return new PrivateKeyInfo(algID, ec.ToAsn1Object()); + return new PrivateKeyInfo(algID, ec); } if (key is Gost3410PrivateKeyParameters) diff --git a/crypto/src/security/PrivateKeyFactory.cs b/crypto/src/security/PrivateKeyFactory.cs index b9538b33d..8c2ecfdb0 100644 --- a/crypto/src/security/PrivateKeyFactory.cs +++ b/crypto/src/security/PrivateKeyFactory.cs @@ -117,8 +117,7 @@ namespace Org.BouncyCastle.Security x9 = new X9ECParameters((Asn1Sequence)para.Parameters); } - ECPrivateKeyStructure ec = new ECPrivateKeyStructure( - Asn1Sequence.GetInstance(keyInfo.ParsePrivateKey())); + ECPrivateKeyStructure ec = ECPrivateKeyStructure.GetInstance(keyInfo.ParsePrivateKey()); BigInteger d = ec.GetKey(); if (para.IsNamedCurve) @@ -134,24 +133,24 @@ namespace Org.BouncyCastle.Security Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters( Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object())); + ECDomainParameters ecP = ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet); + + if (ecP == null) + throw new ArgumentException("Unrecognized curve OID for GostR3410x2001 private key"); + Asn1Object privKey = keyInfo.ParsePrivateKey(); ECPrivateKeyStructure ec; if (privKey is DerInteger) { // TODO Do we need to pass any parameters here? - ec = new ECPrivateKeyStructure(((DerInteger)privKey).Value); + ec = new ECPrivateKeyStructure(ecP.N.BitLength, ((DerInteger)privKey).Value); } else { ec = ECPrivateKeyStructure.GetInstance(privKey); } - ECDomainParameters ecP = ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet); - - if (ecP == null) - throw new ArgumentException("Unrecognized curve OID for GostR3410x2001 private key"); - return new ECPrivateKeyParameters("ECGOST3410", ec.GetKey(), gostParams.PublicKeyParamSet); } else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x94)) diff --git a/crypto/test/src/asn1/test/X9Test.cs b/crypto/test/src/asn1/test/X9Test.cs index e310811ea..db2541f7c 100644 --- a/crypto/test/src/asn1/test/X9Test.cs +++ b/crypto/test/src/asn1/test/X9Test.cs @@ -27,13 +27,13 @@ namespace Org.BouncyCastle.Asn1.Tests + "yUmqLG2UhT0OZgu/hUsclQX+laAh5///////////////9///+XXetBs6YFfDxDIUZSZVECAQED" + "IAADG5xRI+Iki/JrvL20hoDUa7Cggzorv5B9yyqSMjYu"); - private static readonly byte[] namedPriv = Base64.Decode("MCICAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQEECDAGAgEBBAEK"); + private static readonly byte[] namedPriv = Base64.Decode("MDkCAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQEEHzAdAgEBBBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo="); private static readonly byte[] expPriv = Base64.Decode( - "MIHnAgEAMIHXBgcqhkjOPQIBMIHLAgEBMCkGByqGSM49AQECHn///////////////3///////4" - + "AAAAAAAH///////zBXBB5///////////////9///////+AAAAAAAB///////wEHiVXBfoqMGZU" - + "sfTLA9anUKMMJQEC1JiHF9m6FattPgMVAH1zdBaP/jRxtgqFdoahlHXTv6L/BB8DZ2iujhi7ks" - + "/PAFyUmqLG2UhT0OZgu/hUsclQX+laAh5///////////////9///+XXetBs6YFfDxDIUZSZVEC" - + "AQEECDAGAgEBBAEU"); + "MIIBBAIBADCB1wYHKoZIzj0CATCBywIBATApBgcqhkjOPQEBAh5///////////////9///////" + + "+AAAAAAAB///////8wVwQef///////////////f///////gAAAAAAAf//////8BB4lVwX6KjBmVL" + + "H0ywPWp1CjDCUBAtSYhxfZuhWrbT4DFQB9c3QWj/40cbYKhXaGoZR107+i/wQfA2doro4Yu5LPzw" + + "BclJqixtlIU9DmYLv4VLHJUF/pWgIef///////////////f///l13rQbOmBXw8QyFGUmVRAgEBBC" + + "UwIwIBAQQeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU"); private void EncodePublicKey() { @@ -99,14 +99,15 @@ namespace Org.BouncyCastle.Asn1.Tests private void EncodePrivateKey() { - X9ECParameters ecP = X962NamedCurves.GetByOid(X9ObjectIdentifiers.Prime239v3); + X9ECParameters ecP = X962NamedCurves.GetByOid(X9ObjectIdentifiers.Prime192v1); // // named curve // X962Parameters _params = new X962Parameters(X9ObjectIdentifiers.Prime192v1); - PrivateKeyInfo info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.IdECPublicKey, _params), new ECPrivateKeyStructure(BigInteger.Ten).ToAsn1Object()); + PrivateKeyInfo info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.IdECPublicKey, _params), + new ECPrivateKeyStructure(ecP.N.BitLength, BigInteger.Ten).ToAsn1Object()); if (!Arrays.AreEqual(info.GetEncoded(), namedPriv)) { @@ -123,9 +124,12 @@ namespace Org.BouncyCastle.Asn1.Tests // // explicit curve parameters // + ecP = X962NamedCurves.GetByOid(X9ObjectIdentifiers.Prime239v3); + _params = new X962Parameters(ecP); - info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.IdECPublicKey, _params), new ECPrivateKeyStructure(BigInteger.ValueOf(20)).ToAsn1Object()); + info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.IdECPublicKey, _params), + new ECPrivateKeyStructure(ecP.N.BitLength, BigInteger.ValueOf(20)).ToAsn1Object()); if (!Arrays.AreEqual(info.GetEncoded(), expPriv)) { -- cgit 1.5.1 From 21f2eacb456c933df98a59a78143dfd1a05bb951 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sat, 14 Nov 2015 17:29:37 +0700 Subject: Check there is no trailing data in Asn1Object.FromByteArray --- crypto/src/asn1/Asn1Object.cs | 13 +++++++++---- crypto/src/crypto/tls/TlsUtilities.cs | 5 +++-- crypto/test/src/asn1/test/TagTest.cs | 14 +++++++++----- crypto/test/src/openssl/test/ReaderTest.cs | 4 ++-- 4 files changed, 23 insertions(+), 13 deletions(-) (limited to 'crypto/test/src') diff --git a/crypto/src/asn1/Asn1Object.cs b/crypto/src/asn1/Asn1Object.cs index 08bd599c1..a86fdbb4a 100644 --- a/crypto/src/asn1/Asn1Object.cs +++ b/crypto/src/asn1/Asn1Object.cs @@ -13,13 +13,18 @@ namespace Org.BouncyCastle.Asn1 public static Asn1Object FromByteArray( byte[] data) { - try + try { - return new Asn1InputStream(data).ReadObject(); + MemoryStream input = new MemoryStream(data, false); + Asn1InputStream asn1 = new Asn1InputStream(input, data.Length); + Asn1Object result = asn1.ReadObject(); + if (input.Position != input.Length) + throw new IOException("extra data found after object"); + return result; } catch (InvalidCastException) { - throw new IOException("cannot recognise object in stream"); + throw new IOException("cannot recognise object in byte array"); } } @@ -36,7 +41,7 @@ namespace Org.BouncyCastle.Asn1 } catch (InvalidCastException) { - throw new IOException("cannot recognise object in stream"); + throw new IOException("cannot recognise object in stream"); } } diff --git a/crypto/src/crypto/tls/TlsUtilities.cs b/crypto/src/crypto/tls/TlsUtilities.cs index a8c8a2b28..26fb0d5e8 100644 --- a/crypto/src/crypto/tls/TlsUtilities.cs +++ b/crypto/src/crypto/tls/TlsUtilities.cs @@ -529,11 +529,12 @@ namespace Org.BouncyCastle.Crypto.Tls public static Asn1Object ReadAsn1Object(byte[] encoding) { - Asn1InputStream asn1 = new Asn1InputStream(encoding); + MemoryStream input = new MemoryStream(encoding, false); + Asn1InputStream asn1 = new Asn1InputStream(input, encoding.Length); Asn1Object result = asn1.ReadObject(); if (null == result) throw new TlsFatalAlert(AlertDescription.decode_error); - if (null != asn1.ReadObject()) + if (input.Position != input.Length) throw new TlsFatalAlert(AlertDescription.decode_error); return result; } diff --git a/crypto/test/src/asn1/test/TagTest.cs b/crypto/test/src/asn1/test/TagTest.cs index c5fce6dbc..80ca2c0ea 100644 --- a/crypto/test/src/asn1/test/TagTest.cs +++ b/crypto/test/src/asn1/test/TagTest.cs @@ -1,4 +1,5 @@ using System; +using System.IO; using NUnit.Framework; @@ -33,14 +34,17 @@ namespace Org.BouncyCastle.Asn1.Tests public override void PerformTest() { - DerApplicationSpecific app = (DerApplicationSpecific) - Asn1Object.FromByteArray(longTagged); + Asn1InputStream aIn = new Asn1InputStream(longTagged); - app = (DerApplicationSpecific) Asn1Object.FromByteArray(app.GetContents()); + DerApplicationSpecific app = (DerApplicationSpecific)aIn.ReadObject(); - Asn1InputStream aIn = new Asn1InputStream(app.GetContents()); + aIn = new Asn1InputStream(app.GetContents()); - Asn1TaggedObject tagged = (Asn1TaggedObject) aIn.ReadObject(); + app = (DerApplicationSpecific)aIn.ReadObject(); + + aIn = new Asn1InputStream(app.GetContents()); + + Asn1TaggedObject tagged = (Asn1TaggedObject)aIn.ReadObject(); if (tagged.TagNo != 32) { diff --git a/crypto/test/src/openssl/test/ReaderTest.cs b/crypto/test/src/openssl/test/ReaderTest.cs index e3990b562..c0be5c848 100644 --- a/crypto/test/src/openssl/test/ReaderTest.cs +++ b/crypto/test/src/openssl/test/ReaderTest.cs @@ -198,7 +198,7 @@ namespace Org.BouncyCastle.OpenSsl.Tests doDudPasswordTest("3ee7a8", 10, "DER length more than 4 bytes: 57"); doDudPasswordTest("41af75", 11, "unknown tag 16 encountered"); doDudPasswordTest("1704a5", 12, "corrupted stream detected"); - doDudPasswordTest("1c5822", 13, "Unknown object in GetInstance: Org.BouncyCastle.Asn1.DerUtf8String"); + doDudPasswordTest("1c5822", 13, "extra data found after object"); doDudPasswordTest("5a3d16", 14, "corrupted stream detected"); doDudPasswordTest("8d0c97", 15, "corrupted stream detected"); doDudPasswordTest("bc0daf", 16, "corrupted stream detected"); @@ -342,7 +342,7 @@ namespace Org.BouncyCastle.OpenSsl.Tests Fail("issue not detected: " + index); } - catch (IOException e) + catch (Exception e) { if (e.Message.IndexOf(message) < 0) { -- cgit 1.5.1 From d90506bde1ced221486cb3da0a749fc4999f489c Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sat, 14 Nov 2015 21:24:04 +0700 Subject: Only initialise static data once --- crypto/test/src/crypto/test/NaccacheSternTest.cs | 32 ++++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'crypto/test/src') diff --git a/crypto/test/src/crypto/test/NaccacheSternTest.cs b/crypto/test/src/crypto/test/NaccacheSternTest.cs index faa845059..4fa256f12 100644 --- a/crypto/test/src/crypto/test/NaccacheSternTest.cs +++ b/crypto/test/src/crypto/test/NaccacheSternTest.cs @@ -37,12 +37,6 @@ namespace Org.BouncyCastle.Crypto.Tests static readonly NaccacheSternEngine cryptEng = new NaccacheSternEngine(); static readonly NaccacheSternEngine decryptEng = new NaccacheSternEngine(); - static NaccacheSternTest() - { - cryptEng.Debug = debug; - decryptEng.Debug = debug; - } - // Values from NaccacheStern paper static readonly BigInteger a = BigInteger.ValueOf(101); static readonly BigInteger u1 = BigInteger.ValueOf(3); @@ -82,6 +76,22 @@ namespace Org.BouncyCastle.Crypto.Tests // static readonly string edgeInput = "ff6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e"; + static NaccacheSternTest() + { + cryptEng.Debug = debug; + decryptEng.Debug = debug; + + // First the Parameters from the NaccacheStern Paper + // (see http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf ) + + smallPrimes.Add(u1); + smallPrimes.Add(u2); + smallPrimes.Add(u3); + smallPrimes.Add(v1); + smallPrimes.Add(v2); + smallPrimes.Add(v3); + } + public override string Name { get { return "NaccacheStern"; } @@ -91,16 +101,6 @@ namespace Org.BouncyCastle.Crypto.Tests { // Test with given key from NaccacheSternPaper (totally insecure) - // First the Parameters from the NaccacheStern Paper - // (see http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf ) - - smallPrimes.Add(u1); - smallPrimes.Add(u2); - smallPrimes.Add(u3); - smallPrimes.Add(v1); - smallPrimes.Add(v2); - smallPrimes.Add(v3); - NaccacheSternKeyParameters pubParameters = new NaccacheSternKeyParameters(false, g, n, sigma.BitLength); NaccacheSternPrivateKeyParameters privParameters = new NaccacheSternPrivateKeyParameters(g, n, sigma -- cgit 1.5.1 From 632e27e8c5a2f6fec1a90dcb01cf8d848a5aee90 Mon Sep 17 00:00:00 2001 From: David Hook Date: Mon, 16 Nov 2015 14:29:26 +1100 Subject: FIPS DRBG digest/hmac/CTR --- crypto/src/crypto/IEntropySource.cs | 29 ++ crypto/src/crypto/IEntropySourceProvider.cs | 19 + crypto/src/crypto/prng/CtrSP800Drbg.cs | 495 +++++++++++++++++++ crypto/src/crypto/prng/HMacSP800Drbg.cs | 196 ++++++++ crypto/src/crypto/prng/HashSP800Drbg.cs | 295 ++++++++++++ crypto/src/crypto/prng/SP80090Drbg.cs | 33 ++ crypto/src/crypto/prng/Utils.cs | 103 ++++ crypto/src/crypto/prng/drbg/CtrSP800Drbg.cs | 494 +++++++++++++++++++ crypto/src/crypto/prng/drbg/HMacSP800Drbg.cs | 196 ++++++++ crypto/src/crypto/prng/drbg/HashSP800Drbg.cs | 295 ++++++++++++ crypto/src/crypto/prng/drbg/SP80090Drbg.cs | 33 ++ crypto/src/crypto/prng/drbg/Utils.cs | 103 ++++ crypto/test/src/crypto/prng/test/CtrDrbgTest.cs | 524 +++++++++++++++++++++ crypto/test/src/crypto/prng/test/DRGBTestVector.cs | 129 +++++ crypto/test/src/crypto/prng/test/HMacDrbgTest.cs | 511 ++++++++++++++++++++ crypto/test/src/crypto/prng/test/HashDrbgTest.cs | 471 ++++++++++++++++++ .../crypto/prng/test/TestEntropySourceProvider.cs | 64 +++ 17 files changed, 3990 insertions(+) create mode 100644 crypto/src/crypto/IEntropySource.cs create mode 100644 crypto/src/crypto/IEntropySourceProvider.cs create mode 100644 crypto/src/crypto/prng/CtrSP800Drbg.cs create mode 100644 crypto/src/crypto/prng/HMacSP800Drbg.cs create mode 100644 crypto/src/crypto/prng/HashSP800Drbg.cs create mode 100644 crypto/src/crypto/prng/SP80090Drbg.cs create mode 100644 crypto/src/crypto/prng/Utils.cs create mode 100644 crypto/src/crypto/prng/drbg/CtrSP800Drbg.cs create mode 100644 crypto/src/crypto/prng/drbg/HMacSP800Drbg.cs create mode 100644 crypto/src/crypto/prng/drbg/HashSP800Drbg.cs create mode 100644 crypto/src/crypto/prng/drbg/SP80090Drbg.cs create mode 100644 crypto/src/crypto/prng/drbg/Utils.cs create mode 100644 crypto/test/src/crypto/prng/test/CtrDrbgTest.cs create mode 100644 crypto/test/src/crypto/prng/test/DRGBTestVector.cs create mode 100644 crypto/test/src/crypto/prng/test/HMacDrbgTest.cs create mode 100644 crypto/test/src/crypto/prng/test/HashDrbgTest.cs create mode 100644 crypto/test/src/crypto/prng/test/TestEntropySourceProvider.cs (limited to 'crypto/test/src') diff --git a/crypto/src/crypto/IEntropySource.cs b/crypto/src/crypto/IEntropySource.cs new file mode 100644 index 000000000..33ce1b801 --- /dev/null +++ b/crypto/src/crypto/IEntropySource.cs @@ -0,0 +1,29 @@ +using System; + +namespace Org.BouncyCastle.Crypto +{ + /// + /// Base interface describing an entropy source for a DRGB. + /// + public interface IEntropySource + { + /// + /// Return whether or not this entropy source is regarded as prediction resistant. + /// + /// true if this instance is prediction resistant; otherwise, false. + bool IsPredictionResistant { get; } + + /// + /// Return a byte array of entropy. + /// + /// The entropy bytes. + byte[] GetEntropy(); + + /// + /// Return the number of bits of entropy this source can produce. + /// + /// The size, in bits, of the return value of getEntropy. + int EntropySize { get; } + } +} + diff --git a/crypto/src/crypto/IEntropySourceProvider.cs b/crypto/src/crypto/IEntropySourceProvider.cs new file mode 100644 index 000000000..990c6497b --- /dev/null +++ b/crypto/src/crypto/IEntropySourceProvider.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Org.BouncyCastle.Crypto +{ + /// + /// Base interface describing a provider of entropy sources. + /// + public interface IEntropySourceProvider + { + /// + /// Return an entropy source providing a block of entropy. + /// + /// The size of the block of entropy required. + /// An entropy source providing bitsRequired blocks of entropy. + IEntropySource Get(int bitsRequired); + } +} diff --git a/crypto/src/crypto/prng/CtrSP800Drbg.cs b/crypto/src/crypto/prng/CtrSP800Drbg.cs new file mode 100644 index 000000000..089cd17cd --- /dev/null +++ b/crypto/src/crypto/prng/CtrSP800Drbg.cs @@ -0,0 +1,495 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Crypto.Prng.Drbg +{ + /** + * A SP800-90A CTR DRBG. + */ + public class CtrSP800Drbg: SP80090Drbg + { + private static readonly long TDEA_RESEED_MAX = 1L << (32 - 1); + private static readonly long AES_RESEED_MAX = 1L << (48 - 1); + private static readonly int TDEA_MAX_BITS_REQUEST = 1 << (13 - 1); + private static readonly int AES_MAX_BITS_REQUEST = 1 << (19 - 1); + + private IEntropySource _entropySource; + private IBlockCipher _engine; + private int _keySizeInBits; + private int _seedLength; + private int _securityStrength; + + // internal state + private byte[] _Key; + private byte[] _V; + private long _reseedCounter = 0; + private bool _isTDEA = false; + + /** + * Construct a SP800-90A CTR DRBG. + *

    + * Minimum entropy requirement is the security strength requested. + *

    + * @param engine underlying block cipher to use to support DRBG + * @param keySizeInBits size of the key to use with the block cipher. + * @param securityStrength security strength required (in bits) + * @param entropySource source of entropy to use for seeding/reseeding. + * @param personalizationString personalization string to distinguish this DRBG (may be null). + * @param nonce nonce to further distinguish this DRBG (may be null). + */ + public CtrSP800Drbg(IBlockCipher engine, int keySizeInBits, int securityStrength, IEntropySource entropySource, byte[] personalizationString, byte[] nonce) + { + _entropySource = entropySource; + _engine = engine; + + _keySizeInBits = keySizeInBits; + _securityStrength = securityStrength; + _seedLength = keySizeInBits + engine.GetBlockSize() * 8; + _isTDEA = isTDEA(engine); + + if (securityStrength > 256) + { + throw new ArgumentException("Requested security strength is not supported by the derivation function"); + } + + if (getMaxSecurityStrength(engine, keySizeInBits) < securityStrength) + { + throw new ArgumentException("Requested security strength is not supported by block cipher and key size"); + } + + if (entropySource.EntropySize < securityStrength) + { + throw new ArgumentException("Not enough entropy for security strength required"); + } + + byte[] entropy = getEntropy(); // Get_entropy_input + + CTR_DRBG_Instantiate_algorithm(entropy, nonce, personalizationString); + } + + private void CTR_DRBG_Instantiate_algorithm(byte[] entropy, byte[] nonce, + byte[] personalisationString) + { + byte[] seedMaterial = Arrays.Concatenate(entropy, nonce, personalisationString); + byte[] seed = Block_Cipher_df(seedMaterial, _seedLength); + + int outlen = _engine.GetBlockSize(); + + _Key = new byte[(_keySizeInBits + 7) / 8]; + _V = new byte[outlen]; + + // _Key & _V are modified by this call + CTR_DRBG_Update(seed, _Key, _V); + + _reseedCounter = 1; + } + + private void CTR_DRBG_Update(byte[] seed, byte[] key, byte[] v) + { + byte[] temp = new byte[seed.Length]; + byte[] outputBlock = new byte[_engine.GetBlockSize()]; + + int i=0; + int outLen = _engine.GetBlockSize(); + + _engine.Init(true, new KeyParameter(expandKey(key))); + while (i*outLen < seed.Length) + { + addOneTo(v); + _engine.ProcessBlock(v, 0, outputBlock, 0); + + int bytesToCopy = ((temp.Length - i * outLen) > outLen) + ? outLen : (temp.Length - i * outLen); + + Array.Copy(outputBlock, 0, temp, i * outLen, bytesToCopy); + ++i; + } + + XOR(temp, seed, temp, 0); + + Array.Copy(temp, 0, key, 0, key.Length); + Array.Copy(temp, key.Length, v, 0, v.Length); + } + + private void CTR_DRBG_Reseed_algorithm(byte[] additionalInput) + { + byte[] seedMaterial = Arrays.Concatenate(getEntropy(), additionalInput); + + seedMaterial = Block_Cipher_df(seedMaterial, _seedLength); + + CTR_DRBG_Update(seedMaterial, _Key, _V); + + _reseedCounter = 1; + } + + private void XOR(byte[] output, byte[] a, byte[] b, int bOff) + { + for (int i=0; i< output.Length; i++) + { + output[i] = (byte)(a[i] ^ b[i+bOff]); + } + } + + private void addOneTo(byte[] longer) + { + int carry = 1; + for (int i = 1; i <= longer.Length; i++) // warning + { + int res = (longer[longer.Length - i] & 0xff) + carry; + carry = (res > 0xff) ? 1 : 0; + longer[longer.Length - i] = (byte)res; + } + } + + private byte[] getEntropy() + { + byte[] entropy = _entropySource.GetEntropy(); + if (entropy.Length < (_securityStrength + 7) / 8) + { + throw new InvalidOperationException("Insufficient entropy provided by entropy source"); + } + return entropy; + } + + // -- Internal state migration --- + + private static readonly byte[] K_BITS = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"); + + // 1. If (number_of_bits_to_return > max_number_of_bits), then return an + // ERROR_FLAG. + // 2. L = len (input_string)/8. + // 3. N = number_of_bits_to_return/8. + // Comment: L is the bitstring represention of + // the integer resulting from len (input_string)/8. + // L shall be represented as a 32-bit integer. + // + // Comment : N is the bitstring represention of + // the integer resulting from + // number_of_bits_to_return/8. N shall be + // represented as a 32-bit integer. + // + // 4. S = L || N || input_string || 0x80. + // 5. While (len (S) mod outlen) + // Comment : Pad S with zeros, if necessary. + // 0, S = S || 0x00. + // + // Comment : Compute the starting value. + // 6. temp = the Null string. + // 7. i = 0. + // 8. K = Leftmost keylen bits of 0x00010203...1D1E1F. + // 9. While len (temp) < keylen + outlen, do + // + // IV = i || 0outlen - len (i). + // + // 9.1 + // + // temp = temp || BCC (K, (IV || S)). + // + // 9.2 + // + // i = i + 1. + // + // 9.3 + // + // Comment : i shall be represented as a 32-bit + // integer, i.e., len (i) = 32. + // + // Comment: The 32-bit integer represenation of + // i is padded with zeros to outlen bits. + // + // Comment: Compute the requested number of + // bits. + // + // 10. K = Leftmost keylen bits of temp. + // + // 11. X = Next outlen bits of temp. + // + // 12. temp = the Null string. + // + // 13. While len (temp) < number_of_bits_to_return, do + // + // 13.1 X = Block_Encrypt (K, X). + // + // 13.2 temp = temp || X. + // + // 14. requested_bits = Leftmost number_of_bits_to_return of temp. + // + // 15. Return SUCCESS and requested_bits. + private byte[] Block_Cipher_df(byte[] inputString, int bitLength) + { + int outLen = _engine.GetBlockSize(); + int L = inputString.Length; // already in bytes + int N = bitLength / 8; + // 4 S = L || N || inputstring || 0x80 + int sLen = 4 + 4 + L + 1; + int blockLen = ((sLen + outLen - 1) / outLen) * outLen; + byte[] S = new byte[blockLen]; + copyIntToByteArray(S, L, 0); + copyIntToByteArray(S, N, 4); + Array.Copy(inputString, 0, S, 8, L); + S[8 + L] = (byte)0x80; + // S already padded with zeros + + byte[] temp = new byte[_keySizeInBits / 8 + outLen]; + byte[] bccOut = new byte[outLen]; + + byte[] IV = new byte[outLen]; + + int i = 0; + byte[] K = new byte[_keySizeInBits / 8]; + Array.Copy(K_BITS, 0, K, 0, K.Length); + + while (i*outLen*8 < _keySizeInBits + outLen *8) + { + copyIntToByteArray(IV, i, 0); + BCC(bccOut, K, IV, S); + + int bytesToCopy = ((temp.Length - i * outLen) > outLen) + ? outLen + : (temp.Length - i * outLen); + + Array.Copy(bccOut, 0, temp, i * outLen, bytesToCopy); + ++i; + } + + byte[] X = new byte[outLen]; + Array.Copy(temp, 0, K, 0, K.Length); + Array.Copy(temp, K.Length, X, 0, X.Length); + + temp = new byte[bitLength / 2]; + + i = 0; + _engine.Init(true, new KeyParameter(expandKey(K))); + + while (i * outLen < temp.Length) + { + _engine.ProcessBlock(X, 0, X, 0); + + int bytesToCopy = ((temp.Length - i * outLen) > outLen) + ? outLen + : (temp.Length - i * outLen); + + Array.Copy(X, 0, temp, i * outLen, bytesToCopy); + i++; + } + + return temp; + } + + /* + * 1. chaining_value = 0^outlen + * . Comment: Set the first chaining value to outlen zeros. + * 2. n = len (data)/outlen. + * 3. Starting with the leftmost bits of data, split the data into n blocks of outlen bits + * each, forming block(1) to block(n). + * 4. For i = 1 to n do + * 4.1 input_block = chaining_value ^ block(i) . + * 4.2 chaining_value = Block_Encrypt (Key, input_block). + * 5. output_block = chaining_value. + * 6. Return output_block. + */ + private void BCC(byte[] bccOut, byte[] k, byte[] iV, byte[] data) + { + int outlen = _engine.GetBlockSize(); + byte[] chainingValue = new byte[outlen]; // initial values = 0 + int n = data.Length / outlen; + + byte[] inputBlock = new byte[outlen]; + + _engine.Init(true, new KeyParameter(expandKey(k))); + + _engine.ProcessBlock(iV, 0, chainingValue, 0); + + for (int i = 0; i < n; i++) + { + XOR(inputBlock, chainingValue, data, i*outlen); + _engine.ProcessBlock(inputBlock, 0, chainingValue, 0); + } + + Array.Copy(chainingValue, 0, bccOut, 0, bccOut.Length); + } + + private void copyIntToByteArray(byte[] buf, int value, int offSet) + { + buf[offSet + 0] = ((byte)(value >> 24)); + buf[offSet + 1] = ((byte)(value >> 16)); + buf[offSet + 2] = ((byte)(value >> 8)); + buf[offSet + 3] = ((byte)(value)); + } + + /** + * Return the block size (in bits) of the DRBG. + * + * @return the number of bits produced on each internal round of the DRBG. + */ + public int BlockSize + { + get { + return _V.Length * 8; + } + } + + /** + * Populate a passed in array with random data. + * + * @param output output array for generated bits. + * @param additionalInput additional input to be added to the DRBG in this step. + * @param predictionResistant true if a reseed should be forced, false otherwise. + * + * @return number of bits generated, -1 if a reseed required. + */ + public int Generate(byte[] output, byte[] additionalInput, bool predictionResistant) + { + if (_isTDEA) + { + if (_reseedCounter > TDEA_RESEED_MAX) + { + return -1; + } + + if (Utils.isTooLarge(output, TDEA_MAX_BITS_REQUEST / 8)) + { + throw new ArgumentException("Number of bits per request limited to " + TDEA_MAX_BITS_REQUEST); + } + } + else + { + if (_reseedCounter > AES_RESEED_MAX) + { + return -1; + } + + if (Utils.isTooLarge(output, AES_MAX_BITS_REQUEST / 8)) + { + throw new ArgumentException("Number of bits per request limited to " + AES_MAX_BITS_REQUEST); + } + } + + if (predictionResistant) + { + CTR_DRBG_Reseed_algorithm(additionalInput); + additionalInput = null; + } + + if (additionalInput != null) + { + additionalInput = Block_Cipher_df(additionalInput, _seedLength); + CTR_DRBG_Update(additionalInput, _Key, _V); + } + else + { + additionalInput = new byte[_seedLength]; + } + + byte[] tmp = new byte[_V.Length]; + + _engine.Init(true, new KeyParameter(expandKey(_Key))); + + for (int i = 0; i <= output.Length / tmp.Length; i++) + { + int bytesToCopy = ((output.Length - i * tmp.Length) > tmp.Length) + ? tmp.Length + : (output.Length - i * _V.Length); + + if (bytesToCopy != 0) + { + addOneTo(_V); + + _engine.ProcessBlock(_V, 0, tmp, 0); + + Array.Copy(tmp, 0, output, i * tmp.Length, bytesToCopy); + } + } + + CTR_DRBG_Update(additionalInput, _Key, _V); + + _reseedCounter++; + + return output.Length * 8; + } + + /** + * Reseed the DRBG. + * + * @param additionalInput additional input to be added to the DRBG in this step. + */ + public void Reseed(byte[] additionalInput) + { + CTR_DRBG_Reseed_algorithm(additionalInput); + } + + private bool isTDEA(IBlockCipher cipher) + { + return cipher.AlgorithmName.Equals("DESede") || cipher.AlgorithmName.Equals("TDEA"); + } + + private int getMaxSecurityStrength(IBlockCipher cipher, int keySizeInBits) + { + if (isTDEA(cipher) && keySizeInBits == 168) + { + return 112; + } + if (cipher.AlgorithmName.Equals("AES")) + { + return keySizeInBits; + } + + return -1; + } + + byte[] expandKey(byte[] key) + { + if (_isTDEA) + { + // expand key to 192 bits. + byte[] tmp = new byte[24]; + + padKey(key, 0, tmp, 0); + padKey(key, 7, tmp, 8); + padKey(key, 14, tmp, 16); + + return tmp; + } + else + { + return key; + } + } + + /** + * Pad out a key for TDEA, setting odd parity for each byte. + * + * @param keyMaster + * @param keyOff + * @param tmp + * @param tmpOff + */ + private void padKey(byte[] keyMaster, int keyOff, byte[] tmp, int tmpOff) + { + tmp[tmpOff + 0] = (byte)(keyMaster[keyOff + 0] & 0xfe); + tmp[tmpOff + 1] = (byte)((keyMaster[keyOff + 0] << 7) | ((keyMaster[keyOff + 1] & 0xfc) >> 1)); + tmp[tmpOff + 2] = (byte)((keyMaster[keyOff + 1] << 6) | ((keyMaster[keyOff + 2] & 0xf8) >> 2)); + tmp[tmpOff + 3] = (byte)((keyMaster[keyOff + 2] << 5) | ((keyMaster[keyOff + 3] & 0xf0) >> 3)); + tmp[tmpOff + 4] = (byte)((keyMaster[keyOff + 3] << 4) | ((keyMaster[keyOff + 4] & 0xe0) >> 4)); + tmp[tmpOff + 5] = (byte)((keyMaster[keyOff + 4] << 3) | ((keyMaster[keyOff + 5] & 0xc0) >> 5)); + tmp[tmpOff + 6] = (byte)((keyMaster[keyOff + 5] << 2) | ((keyMaster[keyOff + 6] & 0x80) >> 6)); + tmp[tmpOff + 7] = (byte)(keyMaster[keyOff + 6] << 1); + + for (int i = tmpOff; i <= tmpOff + 7; i++) + { + int b = tmp[i]; + tmp[i] = (byte)((b & 0xfe) | + ((((b >> 1) ^ + (b >> 2) ^ + (b >> 3) ^ + (b >> 4) ^ + (b >> 5) ^ + (b >> 6) ^ + (b >> 7)) ^ 0x01) & 0x01)); + } + } + } +} diff --git a/crypto/src/crypto/prng/HMacSP800Drbg.cs b/crypto/src/crypto/prng/HMacSP800Drbg.cs new file mode 100644 index 000000000..b2903766f --- /dev/null +++ b/crypto/src/crypto/prng/HMacSP800Drbg.cs @@ -0,0 +1,196 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Prng.Drbg +{ + /** + * A SP800-90A HMAC DRBG. + */ + public class HMacSP800Drbg: SP80090Drbg + { + private readonly static long RESEED_MAX = 1L << (48 - 1); + private readonly static int MAX_BITS_REQUEST = 1 << (19 - 1); + + private byte[] _K; + private byte[] _V; + private long _reseedCounter; + private IEntropySource _entropySource; + private IMac _hMac; + private int _securityStrength; + + /** + * Construct a SP800-90A Hash DRBG. + *

    + * Minimum entropy requirement is the security strength requested. + *

    + * @param hMac Hash MAC to base the DRBG on. + * @param securityStrength security strength required (in bits) + * @param entropySource source of entropy to use for seeding/reseeding. + * @param personalizationString personalization string to distinguish this DRBG (may be null). + * @param nonce nonce to further distinguish this DRBG (may be null). + */ + public HMacSP800Drbg(IMac hMac, int securityStrength, IEntropySource entropySource, byte[] personalizationString, byte[] nonce) + { + if (securityStrength > Utils.getMaxSecurityStrength(hMac)) + { + throw new ArgumentException("Requested security strength is not supported by the derivation function"); + } + + if (entropySource.EntropySize < securityStrength) + { + throw new ArgumentException("Not enough entropy for security strength required"); + } + + _securityStrength = securityStrength; + _entropySource = entropySource; + _hMac = hMac; + + byte[] entropy = getEntropy(); + byte[] seedMaterial = Arrays.Concatenate(entropy, nonce, personalizationString); + + _K = new byte[hMac.GetMacSize()]; + _V = new byte[_K.Length]; + Arrays.Fill(_V, (byte)1); + + hmac_DRBG_Update(seedMaterial); + + _reseedCounter = 1; + } + + private void hmac_DRBG_Update(byte[] seedMaterial) + { + hmac_DRBG_Update_Func(seedMaterial, (byte)0x00); + if (seedMaterial != null) + { + hmac_DRBG_Update_Func(seedMaterial, (byte)0x01); + } + } + + private void hmac_DRBG_Update_Func(byte[] seedMaterial, byte vValue) + { + _hMac.Init(new KeyParameter(_K)); + + _hMac.BlockUpdate(_V, 0, _V.Length); + _hMac.Update(vValue); + + if (seedMaterial != null) + { + _hMac.BlockUpdate(seedMaterial, 0, seedMaterial.Length); + } + + _hMac.DoFinal(_K, 0); + + _hMac.Init(new KeyParameter(_K)); + _hMac.BlockUpdate(_V, 0, _V.Length); + + _hMac.DoFinal(_V, 0); + } + + /** + * Return the block size (in bits) of the DRBG. + * + * @return the number of bits produced on each round of the DRBG. + */ + public int BlockSize + { + get { + return _V.Length * 8; + } + } + + /** + * Populate a passed in array with random data. + * + * @param output output array for generated bits. + * @param additionalInput additional input to be added to the DRBG in this step. + * @param predictionResistant true if a reseed should be forced, false otherwise. + * + * @return number of bits generated, -1 if a reseed required. + */ + public int Generate(byte[] output, byte[] additionalInput, bool predictionResistant) + { + int numberOfBits = output.Length * 8; + + if (numberOfBits > MAX_BITS_REQUEST) + { + throw new ArgumentException("Number of bits per request limited to " + MAX_BITS_REQUEST); + } + + if (_reseedCounter > RESEED_MAX) + { + return -1; + } + + if (predictionResistant) + { + Reseed(additionalInput); + additionalInput = null; + } + + // 2. + if (additionalInput != null) + { + hmac_DRBG_Update(additionalInput); + } + + // 3. + byte[] rv = new byte[output.Length]; + + int m = output.Length / _V.Length; + + _hMac.Init(new KeyParameter(_K)); + + for (int i = 0; i < m; i++) + { + _hMac.BlockUpdate(_V, 0, _V.Length); + _hMac.DoFinal(_V, 0); + + Array.Copy(_V, 0, rv, i * _V.Length, _V.Length); + } + + if (m * _V.Length < rv.Length) + { + _hMac.BlockUpdate(_V, 0, _V.Length); + _hMac.DoFinal(_V, 0); + + Array.Copy(_V, 0, rv, m * _V.Length, rv.Length - (m * _V.Length)); + } + + hmac_DRBG_Update(additionalInput); + + _reseedCounter++; + + Array.Copy(rv, 0, output, 0, output.Length); + + return numberOfBits; + } + + /** + * Reseed the DRBG. + * + * @param additionalInput additional input to be added to the DRBG in this step. + */ + public void Reseed(byte[] additionalInput) + { + byte[] entropy = getEntropy(); + byte[] seedMaterial = Arrays.Concatenate(entropy, additionalInput); + + hmac_DRBG_Update(seedMaterial); + + _reseedCounter = 1; + } + + private byte[] getEntropy() + { + byte[] entropy = _entropySource.GetEntropy(); + + if (entropy.Length < (_securityStrength + 7) / 8) + { + throw new InvalidOperationException("Insufficient entropy provided by entropy source"); + } + return entropy; + } + } +} diff --git a/crypto/src/crypto/prng/HashSP800Drbg.cs b/crypto/src/crypto/prng/HashSP800Drbg.cs new file mode 100644 index 000000000..b2b386f17 --- /dev/null +++ b/crypto/src/crypto/prng/HashSP800Drbg.cs @@ -0,0 +1,295 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Prng.Drbg +{ + /** + * A SP800-90A Hash DRBG. + */ + public class HashSP800Drbg: SP80090Drbg + { + private readonly static byte[] ONE = { 0x01 }; + + private readonly static long RESEED_MAX = 1L << (48 - 1); + private readonly static int MAX_BITS_REQUEST = 1 << (19 - 1); + + private static readonly IDictionary seedlens = Platform.CreateHashtable(); + + static HashSP800Drbg() + { + seedlens.Add("SHA-1", 440); + seedlens.Add("SHA-224", 440); + seedlens.Add("SHA-256", 440); + seedlens.Add("SHA-512/256", 440); + seedlens.Add("SHA-512/224", 440); + seedlens.Add("SHA-384", 888); + seedlens.Add("SHA-512", 888); + + } + + private IDigest _digest; + private byte[] _V; + private byte[] _C; + private long _reseedCounter; + private IEntropySource _entropySource; + private int _securityStrength; + private int _seedLength; + + /** + * Construct a SP800-90A Hash DRBG. + *

    + * Minimum entropy requirement is the security strength requested. + *

    + * @param digest source digest to use for DRB stream. + * @param securityStrength security strength required (in bits) + * @param entropySource source of entropy to use for seeding/reseeding. + * @param personalizationString personalization string to distinguish this DRBG (may be null). + * @param nonce nonce to further distinguish this DRBG (may be null). + */ + public HashSP800Drbg(IDigest digest, int securityStrength, IEntropySource entropySource, byte[] personalizationString, byte[] nonce) + { + if (securityStrength > Utils.getMaxSecurityStrength(digest)) + { + throw new ArgumentException("Requested security strength is not supported by the derivation function"); + } + + if (entropySource.EntropySize < securityStrength) + { + throw new ArgumentException("Not enough entropy for security strength required"); + } + + _digest = digest; + _entropySource = entropySource; + _securityStrength = securityStrength; + _seedLength = (int)seedlens[digest.AlgorithmName]; + + // 1. seed_material = entropy_input || nonce || personalization_string. + // 2. seed = Hash_df (seed_material, seedlen). + // 3. V = seed. + // 4. C = Hash_df ((0x00 || V), seedlen). Comment: Preceed V with a byte + // of zeros. + // 5. reseed_counter = 1. + // 6. Return V, C, and reseed_counter as the initial_working_state + + byte[] entropy = getEntropy(); + byte[] seedMaterial = Arrays.Concatenate(entropy, nonce, personalizationString); + byte[] seed = Utils.hash_df(_digest, seedMaterial, _seedLength); + + _V = seed; + byte[] subV = new byte[_V.Length + 1]; + Array.Copy(_V, 0, subV, 1, _V.Length); + _C = Utils.hash_df(_digest, subV, _seedLength); + + _reseedCounter = 1; + } + + /** + * Return the block size (in bits) of the DRBG. + * + * @return the number of bits produced on each internal round of the DRBG. + */ + public int BlockSize + { + get { + return _digest.GetDigestSize () * 8; + } + } + + /** + * Populate a passed in array with random data. + * + * @param output output array for generated bits. + * @param additionalInput additional input to be added to the DRBG in this step. + * @param predictionResistant true if a reseed should be forced, false otherwise. + * + * @return number of bits generated, -1 if a reseed required. + */ + public int Generate(byte[] output, byte[] additionalInput, bool predictionResistant) + { + // 1. If reseed_counter > reseed_interval, then return an indication that a + // reseed is required. + // 2. If (additional_input != Null), then do + // 2.1 w = Hash (0x02 || V || additional_input). + // 2.2 V = (V + w) mod 2^seedlen + // . + // 3. (returned_bits) = Hashgen (requested_number_of_bits, V). + // 4. H = Hash (0x03 || V). + // 5. V = (V + H + C + reseed_counter) mod 2^seedlen + // . + // 6. reseed_counter = reseed_counter + 1. + // 7. Return SUCCESS, returned_bits, and the new values of V, C, and + // reseed_counter for the new_working_state. + int numberOfBits = output.Length*8; + + if (numberOfBits > MAX_BITS_REQUEST) + { + throw new ArgumentException("Number of bits per request limited to " + MAX_BITS_REQUEST); + } + + if (_reseedCounter > RESEED_MAX) + { + return -1; + } + + if (predictionResistant) + { + Reseed(additionalInput); + additionalInput = null; + } + + // 2. + if (additionalInput != null) + { + byte[] newInput = new byte[1 + _V.Length + additionalInput.Length]; + newInput[0] = 0x02; + Array.Copy(_V, 0, newInput, 1, _V.Length); + // TODO: inOff / inLength + Array.Copy(additionalInput, 0, newInput, 1 + _V.Length, additionalInput.Length); + byte[] w = hash(newInput); + + addTo(_V, w); + } + + // 3. + byte[] rv = hashgen(_V, numberOfBits); + + // 4. + byte[] subH = new byte[_V.Length + 1]; + Array.Copy(_V, 0, subH, 1, _V.Length); + subH[0] = 0x03; + + byte[] H = hash(subH); + + // 5. + addTo(_V, H); + addTo(_V, _C); + byte[] c = new byte[4]; + c[0] = (byte)(_reseedCounter >> 24); + c[1] = (byte)(_reseedCounter >> 16); + c[2] = (byte)(_reseedCounter >> 8); + c[3] = (byte)_reseedCounter; + + addTo(_V, c); + + _reseedCounter++; + + Array.Copy(rv, 0, output, 0, output.Length); + + return numberOfBits; + } + + private byte[] getEntropy() + { + byte[] entropy = _entropySource.GetEntropy(); + if (entropy.Length < (_securityStrength + 7) / 8) + { + throw new InvalidOperationException("Insufficient entropy provided by entropy source"); + } + return entropy; + } + + // this will always add the shorter length byte array mathematically to the + // longer length byte array. + // be careful.... + private void addTo(byte[] longer, byte[] shorter) + { + int carry = 0; + for (int i=1;i <= shorter.Length; i++) // warning + { + int res = (longer[longer.Length-i] & 0xff) + (shorter[shorter.Length-i] & 0xff) + carry; + carry = (res > 0xff) ? 1 : 0; + longer[longer.Length-i] = (byte)res; + } + + for (int i=shorter.Length+1;i <= longer.Length; i++) // warning + { + int res = (longer[longer.Length-i] & 0xff) + carry; + carry = (res > 0xff) ? 1 : 0; + longer[longer.Length-i] = (byte)res; + } + } + + /** + * Reseed the DRBG. + * + * @param additionalInput additional input to be added to the DRBG in this step. + */ + public void Reseed(byte[] additionalInput) + { + // 1. seed_material = 0x01 || V || entropy_input || additional_input. + // + // 2. seed = Hash_df (seed_material, seedlen). + // + // 3. V = seed. + // + // 4. C = Hash_df ((0x00 || V), seedlen). + // + // 5. reseed_counter = 1. + // + // 6. Return V, C, and reseed_counter for the new_working_state. + // + // Comment: Precede with a byte of all zeros. + byte[] entropy = getEntropy(); + byte[] seedMaterial = Arrays.Concatenate(ONE, _V, entropy, additionalInput); + byte[] seed = Utils.hash_df(_digest, seedMaterial, _seedLength); + + _V = seed; + byte[] subV = new byte[_V.Length + 1]; + subV[0] = 0x00; + Array.Copy(_V, 0, subV, 1, _V.Length); + _C = Utils.hash_df(_digest, subV, _seedLength); + + _reseedCounter = 1; + } + + private byte[] hash(byte[] input) + { + byte[] hash = new byte[_digest.GetDigestSize()]; + doHash(input, hash); + return hash; + } + + private void doHash(byte[] input, byte[] output) + { + _digest.BlockUpdate(input, 0, input.Length); + _digest.DoFinal(output, 0); + } + + // 1. m = [requested_number_of_bits / outlen] + // 2. data = V. + // 3. W = the Null string. + // 4. For i = 1 to m + // 4.1 wi = Hash (data). + // 4.2 W = W || wi. + // 4.3 data = (data + 1) mod 2^seedlen + // . + // 5. returned_bits = Leftmost (requested_no_of_bits) bits of W. + private byte[] hashgen(byte[] input, int lengthInBits) + { + int digestSize = _digest.GetDigestSize(); + int m = (lengthInBits / 8) / digestSize; + + byte[] data = new byte[input.Length]; + Array.Copy(input, 0, data, 0, input.Length); + + byte[] W = new byte[lengthInBits / 8]; + + byte[] dig = new byte[_digest.GetDigestSize()]; + for (int i = 0; i <= m; i++) + { + doHash(data, dig); + + int bytesToCopy = ((W.Length - i * dig.Length) > dig.Length) + ? dig.Length + : (W.Length - i * dig.Length); + Array.Copy(dig, 0, W, i * dig.Length, bytesToCopy); + + addTo(data, ONE); + } + + return W; + } + } +} diff --git a/crypto/src/crypto/prng/SP80090Drbg.cs b/crypto/src/crypto/prng/SP80090Drbg.cs new file mode 100644 index 000000000..c39cf365f --- /dev/null +++ b/crypto/src/crypto/prng/SP80090Drbg.cs @@ -0,0 +1,33 @@ +namespace Org.BouncyCastle.Crypto.Prng.Drbg +{ + /** + * Interface to SP800-90A deterministic random bit generators. + */ + public interface SP80090Drbg + { + /** + * Return the block size of the DRBG. + * + * @return the block size (in bits) produced by each round of the DRBG. + */ + int BlockSize { get; } + + /** + * Populate a passed in array with random data. + * + * @param output output array for generated bits. + * @param additionalInput additional input to be added to the DRBG in this step. + * @param predictionResistant true if a reseed should be forced, false otherwise. + * + * @return number of bits generated, -1 if a reseed required. + */ + int Generate(byte[] output, byte[] additionalInput, bool predictionResistant); + + /** + * Reseed the DRBG. + * + * @param additionalInput additional input to be added to the DRBG in this step. + */ + void Reseed(byte[] additionalInput); + } +} diff --git a/crypto/src/crypto/prng/Utils.cs b/crypto/src/crypto/prng/Utils.cs new file mode 100644 index 000000000..e5fe7d4b2 --- /dev/null +++ b/crypto/src/crypto/prng/Utils.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Prng.Drbg +{ + internal class Utils + { + private static readonly IDictionary maxSecurityStrengths = Platform.CreateHashtable(); + + static Utils() + { + maxSecurityStrengths.Add("SHA-1", 128); + + maxSecurityStrengths.Add("SHA-224", 192); + maxSecurityStrengths.Add("SHA-256", 256); + maxSecurityStrengths.Add("SHA-384", 256); + maxSecurityStrengths.Add("SHA-512", 256); + + maxSecurityStrengths.Add("SHA-512/224", 192); + maxSecurityStrengths.Add("SHA-512/256", 256); + } + + internal static int getMaxSecurityStrength(IDigest d) + { + return (int)maxSecurityStrengths[d.AlgorithmName]; + } + + internal static int getMaxSecurityStrength(IMac m) + { + string name = m.AlgorithmName; + + return (int)maxSecurityStrengths[name.Substring(0, name.IndexOf("/"))]; + } + + /** + * Used by both Dual EC and Hash. + */ + internal static byte[] hash_df(IDigest digest, byte[] seedMaterial, int seedLength) + { + // 1. temp = the Null string. + // 2. . + // 3. counter = an 8-bit binary value representing the integer "1". + // 4. For i = 1 to len do + // Comment : In step 4.1, no_of_bits_to_return + // is used as a 32-bit string. + // 4.1 temp = temp || Hash (counter || no_of_bits_to_return || + // input_string). + // 4.2 counter = counter + 1. + // 5. requested_bits = Leftmost (no_of_bits_to_return) of temp. + // 6. Return SUCCESS and requested_bits. + byte[] temp = new byte[(seedLength + 7) / 8]; + + int len = temp.Length / digest.GetDigestSize(); + int counter = 1; + + byte[] dig = new byte[digest.GetDigestSize()]; + + for (int i = 0; i <= len; i++) + { + digest.Update((byte)counter); + + digest.Update((byte)(seedLength >> 24)); + digest.Update((byte)(seedLength >> 16)); + digest.Update((byte)(seedLength >> 8)); + digest.Update((byte)seedLength); + + digest.BlockUpdate(seedMaterial, 0, seedMaterial.Length); + + digest.DoFinal(dig, 0); + + int bytesToCopy = ((temp.Length - i * dig.Length) > dig.Length) + ? dig.Length + : (temp.Length - i * dig.Length); + Array.Copy(dig, 0, temp, i * dig.Length, bytesToCopy); + + counter++; + } + + // do a left shift to get rid of excess bits. + if (seedLength % 8 != 0) + { + int shift = 8 - (seedLength % 8); + uint carry = 0; + + for (int i = 0; i != temp.Length; i++) + { + uint b = (uint)(temp[i] & 0xff); + temp[i] = (byte)((b >> shift) | (carry << (8 - shift))); + carry = b; + } + } + + return temp; + } + + internal static bool isTooLarge(byte[] bytes, int maxBytes) + { + return bytes != null && bytes.Length > maxBytes; + } + } +} diff --git a/crypto/src/crypto/prng/drbg/CtrSP800Drbg.cs b/crypto/src/crypto/prng/drbg/CtrSP800Drbg.cs new file mode 100644 index 000000000..d9595d530 --- /dev/null +++ b/crypto/src/crypto/prng/drbg/CtrSP800Drbg.cs @@ -0,0 +1,494 @@ +using System; + +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Crypto.Prng.Drbg +{ + /** + * A SP800-90A CTR DRBG. + */ + public class CTRSP800Drbg: SP80090Drbg + { + private static readonly long TDEA_RESEED_MAX = 1L << (32 - 1); + private static readonly long AES_RESEED_MAX = 1L << (48 - 1); + private static readonly int TDEA_MAX_BITS_REQUEST = 1 << (13 - 1); + private static readonly int AES_MAX_BITS_REQUEST = 1 << (19 - 1); + + private IEntropySource _entropySource; + private IBlockCipher _engine; + private int _keySizeInBits; + private int _seedLength; + private int _securityStrength; + + // internal state + private byte[] _Key; + private byte[] _V; + private long _reseedCounter = 0; + private bool _isTDEA = false; + + /** + * Construct a SP800-90A CTR DRBG. + *

    + * Minimum entropy requirement is the security strength requested. + *

    + * @param engine underlying block cipher to use to support DRBG + * @param keySizeInBits size of the key to use with the block cipher. + * @param securityStrength security strength required (in bits) + * @param entropySource source of entropy to use for seeding/reseeding. + * @param personalizationString personalization string to distinguish this DRBG (may be null). + * @param nonce nonce to further distinguish this DRBG (may be null). + */ + public CTRSP800Drbg(IBlockCipher engine, int keySizeInBits, int securityStrength, IEntropySource entropySource, byte[] personalizationString, byte[] nonce) + { + _entropySource = entropySource; + _engine = engine; + + _keySizeInBits = keySizeInBits; + _securityStrength = securityStrength; + _seedLength = keySizeInBits + engine.getBlockSize() * 8; + _isTDEA = isTDEA(engine); + + if (securityStrength > 256) + { + throw new ArgumentException("Requested security strength is not supported by the derivation function"); + } + + if (getMaxSecurityStrength(engine, keySizeInBits) < securityStrength) + { + throw new ArgumentException("Requested security strength is not supported by block cipher and key size"); + } + + if (entropySource.EntropySize < securityStrength) + { + throw new ArgumentException("Not enough entropy for security strength required"); + } + + byte[] entropy = getEntropy(); // Get_entropy_input + + CTR_DRBG_Instantiate_algorithm(entropy, nonce, personalizationString); + } + + private void CTR_DRBG_Instantiate_algorithm(byte[] entropy, byte[] nonce, + byte[] personalisationString) + { + byte[] seedMaterial = Arrays.Concatenate(entropy, nonce, personalisationString); + byte[] seed = Block_Cipher_df(seedMaterial, _seedLength); + + int outlen = _engine.getBlockSize(); + + _Key = new byte[(_keySizeInBits + 7) / 8]; + _V = new byte[outlen]; + + // _Key & _V are modified by this call + CTR_DRBG_Update(seed, _Key, _V); + + _reseedCounter = 1; + } + + private void CTR_DRBG_Update(byte[] seed, byte[] key, byte[] v) + { + byte[] temp = new byte[seed.Length]; + byte[] outputBlock = new byte[_engine.getBlockSize()]; + + int i=0; + int outLen = _engine.getBlockSize(); + + _engine.init(true, new KeyParameter(expandKey(key))); + while (i*outLen < seed.Length) + { + addOneTo(v); + _engine.processBlock(v, 0, outputBlock, 0); + + int bytesToCopy = ((temp.Length - i * outLen) > outLen) + ? outLen : (temp.Length - i * outLen); + + Array.Copy(outputBlock, 0, temp, i * outLen, bytesToCopy); + ++i; + } + + XOR(temp, seed, temp, 0); + + Array.Copy(temp, 0, key, 0, key.Length); + Array.Copy(temp, key.Length, v, 0, v.Length); + } + + private void CTR_DRBG_Reseed_algorithm(byte[] additionalInput) + { + byte[] seedMaterial = Arrays.Concatenate(getEntropy(), additionalInput); + + seedMaterial = Block_Cipher_df(seedMaterial, _seedLength); + + CTR_DRBG_Update(seedMaterial, _Key, _V); + + _reseedCounter = 1; + } + + private void XOR(byte[] output, byte[] a, byte[] b, int bOff) + { + for (int i=0; i< output.Length; i++) + { + output[i] = (byte)(a[i] ^ b[i+bOff]); + } + } + + private void addOneTo(byte[] longer) + { + int carry = 1; + for (int i = 1; i <= longer.Length; i++) // warning + { + int res = (longer[longer.Length - i] & 0xff) + carry; + carry = (res > 0xff) ? 1 : 0; + longer[longer.Length - i] = (byte)res; + } + } + + private byte[] getEntropy() + { + byte[] entropy = _entropySource.getEntropy(); + if (entropy.Length < (_securityStrength + 7) / 8) + { + throw new IllegalStateException("Insufficient entropy provided by entropy source"); + } + return entropy; + } + + // -- Internal state migration --- + + private static final byte[] K_BITS = Hex.decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"); + + // 1. If (number_of_bits_to_return > max_number_of_bits), then return an + // ERROR_FLAG. + // 2. L = len (input_string)/8. + // 3. N = number_of_bits_to_return/8. + // Comment: L is the bitstring represention of + // the integer resulting from len (input_string)/8. + // L shall be represented as a 32-bit integer. + // + // Comment : N is the bitstring represention of + // the integer resulting from + // number_of_bits_to_return/8. N shall be + // represented as a 32-bit integer. + // + // 4. S = L || N || input_string || 0x80. + // 5. While (len (S) mod outlen) + // Comment : Pad S with zeros, if necessary. + // 0, S = S || 0x00. + // + // Comment : Compute the starting value. + // 6. temp = the Null string. + // 7. i = 0. + // 8. K = Leftmost keylen bits of 0x00010203...1D1E1F. + // 9. While len (temp) < keylen + outlen, do + // + // IV = i || 0outlen - len (i). + // + // 9.1 + // + // temp = temp || BCC (K, (IV || S)). + // + // 9.2 + // + // i = i + 1. + // + // 9.3 + // + // Comment : i shall be represented as a 32-bit + // integer, i.e., len (i) = 32. + // + // Comment: The 32-bit integer represenation of + // i is padded with zeros to outlen bits. + // + // Comment: Compute the requested number of + // bits. + // + // 10. K = Leftmost keylen bits of temp. + // + // 11. X = Next outlen bits of temp. + // + // 12. temp = the Null string. + // + // 13. While len (temp) < number_of_bits_to_return, do + // + // 13.1 X = Block_Encrypt (K, X). + // + // 13.2 temp = temp || X. + // + // 14. requested_bits = Leftmost number_of_bits_to_return of temp. + // + // 15. Return SUCCESS and requested_bits. + private byte[] Block_Cipher_df(byte[] inputString, int bitLength) + { + int outLen = _engine.getBlockSize(); + int L = inputString.Length; // already in bytes + int N = bitLength / 8; + // 4 S = L || N || inputstring || 0x80 + int sLen = 4 + 4 + L + 1; + int blockLen = ((sLen + outLen - 1) / outLen) * outLen; + byte[] S = new byte[blockLen]; + copyIntToByteArray(S, L, 0); + copyIntToByteArray(S, N, 4); + Array.Copy(inputString, 0, S, 8, L); + S[8 + L] = (byte)0x80; + // S already padded with zeros + + byte[] temp = new byte[_keySizeInBits / 8 + outLen]; + byte[] bccOut = new byte[outLen]; + + byte[] IV = new byte[outLen]; + + int i = 0; + byte[] K = new byte[_keySizeInBits / 8]; + Array.Copy(K_BITS, 0, K, 0, K.Length); + + while (i*outLen*8 < _keySizeInBits + outLen *8) + { + copyIntToByteArray(IV, i, 0); + BCC(bccOut, K, IV, S); + + int bytesToCopy = ((temp.Length - i * outLen) > outLen) + ? outLen + : (temp.Length - i * outLen); + + Array.Copy(bccOut, 0, temp, i * outLen, bytesToCopy); + ++i; + } + + byte[] X = new byte[outLen]; + Array.Copy(temp, 0, K, 0, K.Length); + Array.Copy(temp, K.Length, X, 0, X.Length); + + temp = new byte[bitLength / 2]; + + i = 0; + _engine.init(true, new KeyParameter(expandKey(K))); + + while (i * outLen < temp.Length) + { + _engine.processBlock(X, 0, X, 0); + + int bytesToCopy = ((temp.Length - i * outLen) > outLen) + ? outLen + : (temp.Length - i * outLen); + + Array.Copy(X, 0, temp, i * outLen, bytesToCopy); + i++; + } + + return temp; + } + + /* + * 1. chaining_value = 0^outlen + * . Comment: Set the first chaining value to outlen zeros. + * 2. n = len (data)/outlen. + * 3. Starting with the leftmost bits of data, split the data into n blocks of outlen bits + * each, forming block(1) to block(n). + * 4. For i = 1 to n do + * 4.1 input_block = chaining_value ^ block(i) . + * 4.2 chaining_value = Block_Encrypt (Key, input_block). + * 5. output_block = chaining_value. + * 6. Return output_block. + */ + private void BCC(byte[] bccOut, byte[] k, byte[] iV, byte[] data) + { + int outlen = _engine.getBlockSize(); + byte[] chainingValue = new byte[outlen]; // initial values = 0 + int n = data.Length / outlen; + + byte[] inputBlock = new byte[outlen]; + + _engine.init(true, new KeyParameter(expandKey(k))); + + _engine.processBlock(iV, 0, chainingValue, 0); + + for (int i = 0; i < n; i++) + { + XOR(inputBlock, chainingValue, data, i*outlen); + _engine.processBlock(inputBlock, 0, chainingValue, 0); + } + + Array.Copy(chainingValue, 0, bccOut, 0, bccOut.Length); + } + + private void copyIntToByteArray(byte[] buf, int value, int offSet) + { + buf[offSet + 0] = ((byte)(value >> 24)); + buf[offSet + 1] = ((byte)(value >> 16)); + buf[offSet + 2] = ((byte)(value >> 8)); + buf[offSet + 3] = ((byte)(value)); + } + + /** + * Return the block size (in bits) of the DRBG. + * + * @return the number of bits produced on each internal round of the DRBG. + */ + public int BlockSize + { + get { + return _V.Length * 8; + } + } + + /** + * Populate a passed in array with random data. + * + * @param output output array for generated bits. + * @param additionalInput additional input to be added to the DRBG in this step. + * @param predictionResistant true if a reseed should be forced, false otherwise. + * + * @return number of bits generated, -1 if a reseed required. + */ + public int Generate(byte[] output, byte[] additionalInput, bool predictionResistant) + { + if (_isTDEA) + { + if (_reseedCounter > TDEA_RESEED_MAX) + { + return -1; + } + + if (Utils.isTooLarge(output, TDEA_MAX_BITS_REQUEST / 8)) + { + throw new ArgumentException("Number of bits per request limited to " + TDEA_MAX_BITS_REQUEST); + } + } + else + { + if (_reseedCounter > AES_RESEED_MAX) + { + return -1; + } + + if (Utils.isTooLarge(output, AES_MAX_BITS_REQUEST / 8)) + { + throw new ArgumentException("Number of bits per request limited to " + AES_MAX_BITS_REQUEST); + } + } + + if (predictionResistant) + { + CTR_DRBG_Reseed_algorithm(additionalInput); + additionalInput = null; + } + + if (additionalInput != null) + { + additionalInput = Block_Cipher_df(additionalInput, _seedLength); + CTR_DRBG_Update(additionalInput, _Key, _V); + } + else + { + additionalInput = new byte[_seedLength]; + } + + byte[] tmp = new byte[_V.Length]; + + _engine.init(true, new KeyParameter(expandKey(_Key))); + + for (int i = 0; i <= output.Length / tmp.Length; i++) + { + int bytesToCopy = ((output.Length - i * tmp.Length) > tmp.Length) + ? tmp.Length + : (output.Length - i * _V.Length); + + if (bytesToCopy != 0) + { + addOneTo(_V); + + _engine.processBlock(_V, 0, tmp, 0); + + Array.Copy(tmp, 0, output, i * tmp.Length, bytesToCopy); + } + } + + CTR_DRBG_Update(additionalInput, _Key, _V); + + _reseedCounter++; + + return output.Length * 8; + } + + /** + * Reseed the DRBG. + * + * @param additionalInput additional input to be added to the DRBG in this step. + */ + public void Reseed(byte[] additionalInput) + { + CTR_DRBG_Reseed_algorithm(additionalInput); + } + + private boolean isTDEA(BlockCipher cipher) + { + return cipher.AlgorithmName.Equals("DESede") || cipher.AlgorithmName.Equals("TDEA"); + } + + private int getMaxSecurityStrength(BlockCipher cipher, int keySizeInBits) + { + if (isTDEA(cipher) && keySizeInBits == 168) + { + return 112; + } + if (cipher.AlgorithmName.Equals("AES")) + { + return keySizeInBits; + } + + return -1; + } + + byte[] expandKey(byte[] key) + { + if (_isTDEA) + { + // expand key to 192 bits. + byte[] tmp = new byte[24]; + + padKey(key, 0, tmp, 0); + padKey(key, 7, tmp, 8); + padKey(key, 14, tmp, 16); + + return tmp; + } + else + { + return key; + } + } + + /** + * Pad out a key for TDEA, setting odd parity for each byte. + * + * @param keyMaster + * @param keyOff + * @param tmp + * @param tmpOff + */ + private void padKey(byte[] keyMaster, int keyOff, byte[] tmp, int tmpOff) + { + tmp[tmpOff + 0] = (byte)(keyMaster[keyOff + 0] & 0xfe); + tmp[tmpOff + 1] = (byte)((keyMaster[keyOff + 0] << 7) | ((keyMaster[keyOff + 1] & 0xfc) >> 1)); + tmp[tmpOff + 2] = (byte)((keyMaster[keyOff + 1] << 6) | ((keyMaster[keyOff + 2] & 0xf8) >> 2)); + tmp[tmpOff + 3] = (byte)((keyMaster[keyOff + 2] << 5) | ((keyMaster[keyOff + 3] & 0xf0) >> 3)); + tmp[tmpOff + 4] = (byte)((keyMaster[keyOff + 3] << 4) | ((keyMaster[keyOff + 4] & 0xe0) >> 4)); + tmp[tmpOff + 5] = (byte)((keyMaster[keyOff + 4] << 3) | ((keyMaster[keyOff + 5] & 0xc0) >> 5)); + tmp[tmpOff + 6] = (byte)((keyMaster[keyOff + 5] << 2) | ((keyMaster[keyOff + 6] & 0x80) >> 6)); + tmp[tmpOff + 7] = (byte)(keyMaster[keyOff + 6] << 1); + + for (int i = tmpOff; i <= tmpOff + 7; i++) + { + int b = tmp[i]; + tmp[i] = (byte)((b & 0xfe) | + ((((b >> 1) ^ + (b >> 2) ^ + (b >> 3) ^ + (b >> 4) ^ + (b >> 5) ^ + (b >> 6) ^ + (b >> 7)) ^ 0x01) & 0x01)); + } + } + } +} diff --git a/crypto/src/crypto/prng/drbg/HMacSP800Drbg.cs b/crypto/src/crypto/prng/drbg/HMacSP800Drbg.cs new file mode 100644 index 000000000..78a710097 --- /dev/null +++ b/crypto/src/crypto/prng/drbg/HMacSP800Drbg.cs @@ -0,0 +1,196 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Prng.Drbg +{ + /** + * A SP800-90A HMAC DRBG. + */ + public class HMacSP800Drbg: SP80090Drbg + { + private readonly static long RESEED_MAX = 1L << (48 - 1); + private readonly static int MAX_BITS_REQUEST = 1 << (19 - 1); + + private byte[] _K; + private byte[] _V; + private long _reseedCounter; + private EntropySource _entropySource; + private Mac _hMac; + private int _securityStrength; + + /** + * Construct a SP800-90A Hash DRBG. + *

    + * Minimum entropy requirement is the security strength requested. + *

    + * @param hMac Hash MAC to base the DRBG on. + * @param securityStrength security strength required (in bits) + * @param entropySource source of entropy to use for seeding/reseeding. + * @param personalizationString personalization string to distinguish this DRBG (may be null). + * @param nonce nonce to further distinguish this DRBG (may be null). + */ + public HMacSP800Drbg(IMac hMac, int securityStrength, IEntropySource entropySource, byte[] personalizationString, byte[] nonce) + { + if (securityStrength > Utils.getMaxSecurityStrength(hMac)) + { + throw new ArgumentException("Requested security strength is not supported by the derivation function"); + } + + if (entropySource.EntropySize < securityStrength) + { + throw new ArgumentException("Not enough entropy for security strength required"); + } + + _securityStrength = securityStrength; + _entropySource = entropySource; + _hMac = hMac; + + byte[] entropy = getEntropy(); + byte[] seedMaterial = Arrays.Concatenate(entropy, nonce, personalizationString); + + _K = new byte[hMac.GetMacSize()]; + _V = new byte[_K.Length]; + Arrays.fill(_V, (byte)1); + + hmac_DRBG_Update(seedMaterial); + + _reseedCounter = 1; + } + + private void hmac_DRBG_Update(byte[] seedMaterial) + { + hmac_DRBG_Update_Func(seedMaterial, (byte)0x00); + if (seedMaterial != null) + { + hmac_DRBG_Update_Func(seedMaterial, (byte)0x01); + } + } + + private void hmac_DRBG_Update_Func(byte[] seedMaterial, byte vValue) + { + _hMac.Init(new KeyParameter(_K)); + + _hMac.BlockUpdate(_V, 0, _V.Length); + _hMac.Update(vValue); + + if (seedMaterial != null) + { + _hMac.update(seedMaterial, 0, seedMaterial.Length); + } + + _hMac.DoFinal(_K, 0); + + _hMac.Init(new KeyParameter(_K)); + _hMac.BlockUpdate(_V, 0, _V.Length); + + _hMac.DoFinal(_V, 0); + } + + /** + * Return the block size (in bits) of the DRBG. + * + * @return the number of bits produced on each round of the DRBG. + */ + public int BlockSize + { + get { + return _V.Length * 8; + } + } + + /** + * Populate a passed in array with random data. + * + * @param output output array for generated bits. + * @param additionalInput additional input to be added to the DRBG in this step. + * @param predictionResistant true if a reseed should be forced, false otherwise. + * + * @return number of bits generated, -1 if a reseed required. + */ + public int Generate(byte[] output, byte[] additionalInput, boolean predictionResistant) + { + int numberOfBits = output.Length * 8; + + if (numberOfBits > MAX_BITS_REQUEST) + { + throw new IllegalArgumentException("Number of bits per request limited to " + MAX_BITS_REQUEST); + } + + if (_reseedCounter > RESEED_MAX) + { + return -1; + } + + if (predictionResistant) + { + reseed(additionalInput); + additionalInput = null; + } + + // 2. + if (additionalInput != null) + { + hmac_DRBG_Update(additionalInput); + } + + // 3. + byte[] rv = new byte[output.Length]; + + int m = output.Length / _V.Length; + + _hMac.Init(new KeyParameter(_K)); + + for (int i = 0; i < m; i++) + { + _hMac.BlockUpdate(_V, 0, _V.Length); + _hMac.DoFinal(_V, 0); + + Array.Copy(_V, 0, rv, i * _V.Length, _V.Length); + } + + if (m * _V.Length < rv.Length) + { + _hMac.BlockUpdate(_V, 0, _V.Length); + _hMac.DoFinal(_V, 0); + + Array.Copy(_V, 0, rv, m * _V.Length, rv.Length - (m * _V.Length)); + } + + hmac_DRBG_Update(additionalInput); + + _reseedCounter++; + + Array.Copy(rv, 0, output, 0, output.Length); + + return numberOfBits; + } + + /** + * Reseed the DRBG. + * + * @param additionalInput additional input to be added to the DRBG in this step. + */ + public void Reseed(byte[] additionalInput) + { + byte[] entropy = getEntropy(); + byte[] seedMaterial = Arrays.Concatenate(entropy, additionalInput); + + hmac_DRBG_Update(seedMaterial); + + _reseedCounter = 1; + } + + private byte[] getEntropy() + { + byte[] entropy = _entropySource.GetEntropy(); + + if (entropy.Length < (_securityStrength + 7) / 8) + { + throw new IllegalStateException("Insufficient entropy provided by entropy source"); + } + return entropy; + } + } +} diff --git a/crypto/src/crypto/prng/drbg/HashSP800Drbg.cs b/crypto/src/crypto/prng/drbg/HashSP800Drbg.cs new file mode 100644 index 000000000..868778817 --- /dev/null +++ b/crypto/src/crypto/prng/drbg/HashSP800Drbg.cs @@ -0,0 +1,295 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Prng.Drbg +{ + /** + * A SP800-90A Hash DRBG. + */ + public class HashSP800Drbg: SP80090Drbg + { + private readonly static byte[] ONE = { 0x01 }; + + private readonly static long RESEED_MAX = 1L << (48 - 1); + private readonly static int MAX_BITS_REQUEST = 1 << (19 - 1); + + private static readonly IDictionary seedlens = Platform.CreateHashtable(); + + static HashSP800Drbg() + { + seedlens.Add("SHA-1", 440); + seedlens.Add("SHA-224", 440); + seedlens.Add("SHA-256", 440); + seedlens.Add("SHA-512/256", 440); + seedlens.Add("SHA-512/224", 440); + seedlens.Add("SHA-384", 888); + seedlens.Add("SHA-512", 888); + + } + + private IDigest _digest; + private byte[] _V; + private byte[] _C; + private long _reseedCounter; + private IEntropySource _entropySource; + private int _securityStrength; + private int _seedLength; + + /** + * Construct a SP800-90A Hash DRBG. + *

    + * Minimum entropy requirement is the security strength requested. + *

    + * @param digest source digest to use for DRB stream. + * @param securityStrength security strength required (in bits) + * @param entropySource source of entropy to use for seeding/reseeding. + * @param personalizationString personalization string to distinguish this DRBG (may be null). + * @param nonce nonce to further distinguish this DRBG (may be null). + */ + public HashSP800Drbg(IDigest digest, int securityStrength, IEntropySource entropySource, byte[] personalizationString, byte[] nonce) + { + if (securityStrength > Utils.getMaxSecurityStrength(digest)) + { + throw new ArgumentException("Requested security strength is not supported by the derivation function"); + } + + if (entropySource.EntropySize < securityStrength) + { + throw new ArgumentException("Not enough entropy for security strength required"); + } + + _digest = digest; + _entropySource = entropySource; + _securityStrength = securityStrength; + _seedLength = ((Integer)seedlens.get(digest.getAlgorithmName())).intValue(); + + // 1. seed_material = entropy_input || nonce || personalization_string. + // 2. seed = Hash_df (seed_material, seedlen). + // 3. V = seed. + // 4. C = Hash_df ((0x00 || V), seedlen). Comment: Preceed V with a byte + // of zeros. + // 5. reseed_counter = 1. + // 6. Return V, C, and reseed_counter as the initial_working_state + + byte[] entropy = getEntropy(); + byte[] seedMaterial = Arrays.Concatenate(entropy, nonce, personalizationString); + byte[] seed = Utils.hash_df(_digest, seedMaterial, _seedLength); + + _V = seed; + byte[] subV = new byte[_V.Length + 1]; + Array.Copy(_V, 0, subV, 1, _V.Length); + _C = Utils.hash_df(_digest, subV, _seedLength); + + _reseedCounter = 1; + } + + /** + * Return the block size (in bits) of the DRBG. + * + * @return the number of bits produced on each internal round of the DRBG. + */ + public int BlockSize + { + get { + return _digest.GetDigestSize () * 8; + } + } + + /** + * Populate a passed in array with random data. + * + * @param output output array for generated bits. + * @param additionalInput additional input to be added to the DRBG in this step. + * @param predictionResistant true if a reseed should be forced, false otherwise. + * + * @return number of bits generated, -1 if a reseed required. + */ + public int Generate(byte[] output, byte[] additionalInput, bool predictionResistant) + { + // 1. If reseed_counter > reseed_interval, then return an indication that a + // reseed is required. + // 2. If (additional_input != Null), then do + // 2.1 w = Hash (0x02 || V || additional_input). + // 2.2 V = (V + w) mod 2^seedlen + // . + // 3. (returned_bits) = Hashgen (requested_number_of_bits, V). + // 4. H = Hash (0x03 || V). + // 5. V = (V + H + C + reseed_counter) mod 2^seedlen + // . + // 6. reseed_counter = reseed_counter + 1. + // 7. Return SUCCESS, returned_bits, and the new values of V, C, and + // reseed_counter for the new_working_state. + int numberOfBits = output.Length*8; + + if (numberOfBits > MAX_BITS_REQUEST) + { + throw new ArgumentException("Number of bits per request limited to " + MAX_BITS_REQUEST); + } + + if (_reseedCounter > RESEED_MAX) + { + return -1; + } + + if (predictionResistant) + { + reseed(additionalInput); + additionalInput = null; + } + + // 2. + if (additionalInput != null) + { + byte[] newInput = new byte[1 + _V.Length + additionalInput.Length]; + newInput[0] = 0x02; + Array.Copy(_V, 0, newInput, 1, _V.Length); + // TODO: inOff / inLength + Array.Copy(additionalInput, 0, newInput, 1 + _V.Length, additionalInput.Length); + byte[] w = hash(newInput); + + addTo(_V, w); + } + + // 3. + byte[] rv = hashgen(_V, numberOfBits); + + // 4. + byte[] subH = new byte[_V.Length + 1]; + Array.Copy(_V, 0, subH, 1, _V.Length); + subH[0] = 0x03; + + byte[] H = hash(subH); + + // 5. + addTo(_V, H); + addTo(_V, _C); + byte[] c = new byte[4]; + c[0] = (byte)(_reseedCounter >> 24); + c[1] = (byte)(_reseedCounter >> 16); + c[2] = (byte)(_reseedCounter >> 8); + c[3] = (byte)_reseedCounter; + + addTo(_V, c); + + _reseedCounter++; + + Array.Copy(rv, 0, output, 0, output.Length); + + return numberOfBits; + } + + private byte[] getEntropy() + { + byte[] entropy = _entropySource.getEntropy(); + if (entropy.Length < (_securityStrength + 7) / 8) + { + throw new IllegalStateException("Insufficient entropy provided by entropy source"); + } + return entropy; + } + + // this will always add the shorter length byte array mathematically to the + // longer length byte array. + // be careful.... + private void addTo(byte[] longer, byte[] shorter) + { + int carry = 0; + for (int i=1;i <= shorter.Length; i++) // warning + { + int res = (longer[longer.Length-i] & 0xff) + (shorter[shorter.Length-i] & 0xff) + carry; + carry = (res > 0xff) ? 1 : 0; + longer[longer.Length-i] = (byte)res; + } + + for (int i=shorter.Length+1;i <= longer.Length; i++) // warning + { + int res = (longer[longer.Length-i] & 0xff) + carry; + carry = (res > 0xff) ? 1 : 0; + longer[longer.Length-i] = (byte)res; + } + } + + /** + * Reseed the DRBG. + * + * @param additionalInput additional input to be added to the DRBG in this step. + */ + public void Reseed(byte[] additionalInput) + { + // 1. seed_material = 0x01 || V || entropy_input || additional_input. + // + // 2. seed = Hash_df (seed_material, seedlen). + // + // 3. V = seed. + // + // 4. C = Hash_df ((0x00 || V), seedlen). + // + // 5. reseed_counter = 1. + // + // 6. Return V, C, and reseed_counter for the new_working_state. + // + // Comment: Precede with a byte of all zeros. + byte[] entropy = getEntropy(); + byte[] seedMaterial = Arrays.Concatenate(ONE, _V, entropy, additionalInput); + byte[] seed = Utils.hash_df(_digest, seedMaterial, _seedLength); + + _V = seed; + byte[] subV = new byte[_V.Length + 1]; + subV[0] = 0x00; + Array.Copy(_V, 0, subV, 1, _V.Length); + _C = Utils.hash_df(_digest, subV, _seedLength); + + _reseedCounter = 1; + } + + private byte[] hash(byte[] input) + { + byte[] hash = new byte[_digest.GetDigestSize()]; + doHash(input, hash); + return hash; + } + + private void doHash(byte[] input, byte[] output) + { + _digest.BlockUpdate(input, 0, input.Length); + _digest.DoFinal(output, 0); + } + + // 1. m = [requested_number_of_bits / outlen] + // 2. data = V. + // 3. W = the Null string. + // 4. For i = 1 to m + // 4.1 wi = Hash (data). + // 4.2 W = W || wi. + // 4.3 data = (data + 1) mod 2^seedlen + // . + // 5. returned_bits = Leftmost (requested_no_of_bits) bits of W. + private byte[] hashgen(byte[] input, int lengthInBits) + { + int digestSize = _digest.GetDigestSize(); + int m = (lengthInBits / 8) / digestSize; + + byte[] data = new byte[input.Length]; + Array.Copy(input, 0, data, 0, input.Length); + + byte[] W = new byte[lengthInBits / 8]; + + byte[] dig = new byte[_digest.GetDigestSize()]; + for (int i = 0; i <= m; i++) + { + doHash(data, dig); + + int bytesToCopy = ((W.Length - i * dig.Length) > dig.Length) + ? dig.Length + : (W.Length - i * dig.Length); + Array.Copy(dig, 0, W, i * dig.Length, bytesToCopy); + + addTo(data, ONE); + } + + return W; + } + } +} diff --git a/crypto/src/crypto/prng/drbg/SP80090Drbg.cs b/crypto/src/crypto/prng/drbg/SP80090Drbg.cs new file mode 100644 index 000000000..c39cf365f --- /dev/null +++ b/crypto/src/crypto/prng/drbg/SP80090Drbg.cs @@ -0,0 +1,33 @@ +namespace Org.BouncyCastle.Crypto.Prng.Drbg +{ + /** + * Interface to SP800-90A deterministic random bit generators. + */ + public interface SP80090Drbg + { + /** + * Return the block size of the DRBG. + * + * @return the block size (in bits) produced by each round of the DRBG. + */ + int BlockSize { get; } + + /** + * Populate a passed in array with random data. + * + * @param output output array for generated bits. + * @param additionalInput additional input to be added to the DRBG in this step. + * @param predictionResistant true if a reseed should be forced, false otherwise. + * + * @return number of bits generated, -1 if a reseed required. + */ + int Generate(byte[] output, byte[] additionalInput, bool predictionResistant); + + /** + * Reseed the DRBG. + * + * @param additionalInput additional input to be added to the DRBG in this step. + */ + void Reseed(byte[] additionalInput); + } +} diff --git a/crypto/src/crypto/prng/drbg/Utils.cs b/crypto/src/crypto/prng/drbg/Utils.cs new file mode 100644 index 000000000..b5f3b5830 --- /dev/null +++ b/crypto/src/crypto/prng/drbg/Utils.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Prng.Drbg +{ + internal class Utils + { + private static readonly IDictionary maxSecurityStrengths = Platform.CreateHashtable(); + + static Utils() + { + maxSecurityStrengths.put("SHA-1", 128); + + maxSecurityStrengths.put("SHA-224", 192); + maxSecurityStrengths.put("SHA-256", 256); + maxSecurityStrengths.put("SHA-384", 256); + maxSecurityStrengths.put("SHA-512", 256); + + maxSecurityStrengths.put("SHA-512/224", 192); + maxSecurityStrengths.put("SHA-512/256", 256); + } + + internal static int getMaxSecurityStrength(IDigest d) + { + return (int)maxSecurityStrengths[d.AlgorithmName]; + } + + internal static int getMaxSecurityStrength(IMac m) + { + String name = m.getAlgorithmName(); + + return (int)maxSecurityStrengths[name.substring(0, name.indexOf("/"))]; + } + + /** + * Used by both Dual EC and Hash. + */ + internal static byte[] hash_df(Digest digest, byte[] seedMaterial, int seedLength) + { + // 1. temp = the Null string. + // 2. . + // 3. counter = an 8-bit binary value representing the integer "1". + // 4. For i = 1 to len do + // Comment : In step 4.1, no_of_bits_to_return + // is used as a 32-bit string. + // 4.1 temp = temp || Hash (counter || no_of_bits_to_return || + // input_string). + // 4.2 counter = counter + 1. + // 5. requested_bits = Leftmost (no_of_bits_to_return) of temp. + // 6. Return SUCCESS and requested_bits. + byte[] temp = new byte[(seedLength + 7) / 8]; + + int len = temp.Length / digest.getDigestSize(); + int counter = 1; + + byte[] dig = new byte[digest.getDigestSize()]; + + for (int i = 0; i <= len; i++) + { + digest.Update((byte)counter); + + digest.Update((byte)(seedLength >> 24)); + digest.Update((byte)(seedLength >> 16)); + digest.Update((byte)(seedLength >> 8)); + digest.Update((byte)seedLength); + + digest.BlockUpdate(seedMaterial, 0, seedMaterial.Length); + + digest.DoFinal(dig, 0); + + int bytesToCopy = ((temp.Length - i * dig.Length) > dig.Length) + ? dig.Length + : (temp.Length - i * dig.Length); + Array.Copy(dig, 0, temp, i * dig.Length, bytesToCopy); + + counter++; + } + + // do a left shift to get rid of excess bits. + if (seedLength % 8 != 0) + { + int shift = 8 - (seedLength % 8); + int carry = 0; + + for (int i = 0; i != temp.Length; i++) + { + uint b = temp[i] & 0xff; + temp[i] = (byte)((b >> shift) | (carry << (8 - shift))); + carry = b; + } + } + + return temp; + } + + internal static boolean isTooLarge(byte[] bytes, int maxBytes) + { + return bytes != null && bytes.Length > maxBytes; + } + } +} diff --git a/crypto/test/src/crypto/prng/test/CtrDrbgTest.cs b/crypto/test/src/crypto/prng/test/CtrDrbgTest.cs new file mode 100644 index 000000000..e081ec132 --- /dev/null +++ b/crypto/test/src/crypto/prng/test/CtrDrbgTest.cs @@ -0,0 +1,524 @@ +using System; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Prng.Drbg; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.Utilities.Encoders; +using NUnit.Framework; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Prng.Test +{ + /** + * CTR DRBG Test + */ + [TestFixture] + public class CtrDrbgTest : SimpleTest + { + public override String Name { + get { + return "CTRDRBGTest"; + } + } + + public static void main(String[] args) + { + RunTest(new CtrDrbgTest()); + } + + private DRBGTestVector[] createTestVectorData() + { + return new DRBGTestVector[] + { + new DRBGTestVector( + new DesEdeEngine(), 168, + new Bit232EntropyProvider().Get(232), + false, + "20212223242526", + 112, + new String[] + { + "ABC88224514D0316EA3D48AEE3C9A2B4", + "D3D3F372E43E7ABDC4FA293743EED076" + } + ), + new DRBGTestVector( + new DesEdeEngine(), 168, + new Bit232EntropyProvider().Get(232), + false, + "20212223242526", + 112, + new String[] + { + "D4564EE072ACA5BD279536E14F94CB12", + "1CCD9AFEF15A9679BA75E35225585DEA" + } + ) + .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C") + .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBC"), + new DRBGTestVector( + new DesEdeEngine(), 168, + new Bit232EntropyProvider().Get(232), + false, + "20212223242526", + 112, + new String[] + { + "760BED7D92B083B10AF31CF0656081EB", + "FD1AC41482384D823CF3FD6F0E6C88B3" + } + ) + .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C"), + new DRBGTestVector( + new DesEdeEngine(), 168, + new Bit232EntropyProvider().Get(232), + false, + "20212223242526", + 112, + new String[] + { + "7A4C1D7ADC8A67FDB50100ED23583A2C", + "43044D311C0E07541CA5C8B0916976B2" + } + ) + .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C") + .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C") + .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBC"), + new DRBGTestVector( + new DesEdeEngine(), 168, + new Bit232EntropyProvider().Get(232), + true, + "20212223242526", + 112, + new String[] + { + "8FB78ABCA75C9F284E974E36141866BC", + "9D9745FF31C42A4488CBB771B13B5D86" + } + ), + new DRBGTestVector( + new DesEdeEngine(), 168, + new Bit232EntropyProvider().Get(232), + true, + "20212223242526", + 112, + new String[] + { + "0E389920A09B485AA4ABD0CA7E60D89C", + "F4478EC6659A0D3577625B0C73A211DD" + } + ) + .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C") + .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBC"), + new DRBGTestVector( + new DesEdeEngine(), 168, + new Bit232EntropyProvider().Get(232), + true, + "20212223242526", + 112, + new String[] + { + "64983055D014550B39DE699E43130B64", + "035FDDA8582A2214EC722C410A8D95D3" + } + ) + .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C"), + new DRBGTestVector( + new DesEdeEngine(), 168, + new Bit232EntropyProvider().Get(232), + true, + "20212223242526", + 112, + new String[] + { + "A29C1A8C42FBC562D7D1DBA7DC541FFE", + "0BDA66B049429061C013E4228C2F44C6" + } + ) + .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C") + .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C") + .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBC"), + new DRBGTestVector( + new AesFastEngine(), 128, + new Bit256EntropyProvider().Get(256), + false, + "2021222324252627", + 128, + new String[] + { + "8CF59C8CF6888B96EB1C1E3E79D82387AF08A9E5FF75E23F1FBCD4559B6B997E", + "69CDEF912C692D61B1DA4C05146B52EB7B8849BD87937835328254EC25A9180E" + } + ), + new DRBGTestVector( + new AesFastEngine(), 128, + new Bit256EntropyProvider().Get(256), + false, + "2021222324252627", + 128, + new String[] + { + "E8C74A4B7BFFB53BEB80E78CA86BB6DF70E2032AEB473E0DD54D2339CEFCE9D0", + "26B3F823B4DBAFC23B141375E10B3AEB7A0B5DEF1C7D760B6F827D01ECD17AC7" + } + ) + .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F") + .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"), + new DRBGTestVector( + new AesFastEngine(), 128, + new Bit256EntropyProvider().Get(256), + false, + "2021222324252627", + 128, + new String[] + { + "18FDEFBDC43D7A36D5D6D862205765D1D701C9F237007030DF1B8E70EE4EEE29", + "9888F1D38BB1CCE31B363AA1BD9B39616876C30DEE1FF0B7BD8C4C441715C833" + } + ) + .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F"), + new DRBGTestVector( + new AesFastEngine(), 128, + new Bit256EntropyProvider().Get(256), + true, + "2021222324252627", + 128, + new String[] + { + "BFF4B85D68C84529F24F69F9ACF1756E29BA648DDEB825C225FA32BA490EF4A9", + "9BD2635137A52AF7D0FCBEFEFB97EA93A0F4C438BD98956C0DACB04F15EE25B3" + } + ), + new DRBGTestVector( + new AesFastEngine(), 128, + new Bit256EntropyProvider().Get(256), + true, + "2021222324252627", + 128, + new String[] + { + "4573AC8BBB33D7CC4DBEF3EEDF6EAE748B536C3A1082CEE4948CDB51C83A7F9C", + "99C628CDD87BD8C2F1FE443AA7F761DA16886436326323354DA6311FFF5BC678" + } + ) + .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F") + .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"), + new DRBGTestVector( + new AesFastEngine(), 128, + new Bit256EntropyProvider().Get(256), + true, + "2021222324252627", + 128, + new String[] + { + "F324104E2FA14F79D8AA60DF06B93B3BC157324958F0A7EE1E193677A70E0250", + "78F4C840134F40DC001BFAD3A90B5EF4DEBDBFAC3CFDF0CD69A89DC4FD34713F" + } + ) + .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F"), + new DRBGTestVector( + new AesFastEngine(), 192, + new Bit320EntropyProvider().Get(320), + false, + "202122232425262728292A2B", + 192, + new String[] + { + "E231244B3235B085C81604424357E85201E3828B5C45568679A5555F867AAC8C", + "DDD0F7BCCADADAA31A67652259CE569A271DD85CF66C3D6A7E9FAED61F38D219" + } + ) + .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F6061626364656667"), + new DRBGTestVector( + new AesFastEngine(), 192, + new Bit320EntropyProvider().Get(320), + true, + "202122232425262728292A2B", + 192, + new String[] + { + "F780D4A2C25CF8EE7407D948EC0B724A4235D8B20E65081392755CA7912AD7C0", + "BA14617F915BA964CB79276BDADC840C14B631BBD1A59097054FA6DFF863B238" + } + ) + .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F6061626364656667"), + new DRBGTestVector( + new AesFastEngine(), 256, + new Bit384EntropyProvider().Get(384), + false, + "202122232425262728292A2B2C2D2E2F", + 256, + new String[] + { + "47111E146562E9AA2FB2A1B095D37A8165AF8FC7CA611D632BE7D4C145C83900", + "98A28E3B1BA363C9DAF0F6887A1CF52B833D3354D77A7C10837DD63DD2E645F8" + } + ) + .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F") + .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F") + .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"), + new DRBGTestVector( + new AesFastEngine(), 256, + new Bit384EntropyProvider().Get(384), + true, + "202122232425262728292A2B2C2D2E2F", + 256, + new String[] + { + "71BB3F9C9CEAF4E6C92A83EB4C7225010EE150AC75E23F5F77AD5073EF24D88A", + "386DEBBBF091BBF0502957B0329938FB836B82E594A2F5FDD5EB28D4E35528F4" + } + ) + .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F") + .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"), + new DRBGTestVector( + new AesFastEngine(), 256, + new Bit384EntropyProvider().Get(384), + true, + "202122232425262728292A2B2C2D2E2F", + 256, + new String[] + { + "1A2E3FEE9056E98D375525FDC2B63B95B47CE51FCF594D804BD5A17F2E01139B", + "601F95384F0D85946301D1EACE8F645A825CE38F1E2565B0C0C439448E9CA8AC" + } + ) + .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F"), + new DRBGTestVector( + new AesFastEngine(), 256, + new Bit384EntropyProvider().Get(384), + true, + "202122232425262728292A2B2C2D2E2F", + 256, + new String[] + { + "EAE6BCE781807E524D26605EA198077932D01EEB445B9AC6C5D99C101D29F46E", + "738E99C95AF59519AAD37FF3D5180986ADEBAB6E95836725097E50A8D1D0BD28" + } + ) + .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F") + .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F") + .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"), + new DRBGTestVector( + new AesFastEngine(), 256, + new Bit384EntropyProvider().Get(384), + true, + "202122232425262728292A2B2C2D2E2F", + 256, + new String[] + { + "eae6bce781807e524d26605ea198077932d01eeb445b9ac6c5d99c101d29f46e30b27377", + "ec51b55b49904c3ff9e13939f1cf27398993e1b3acb2b0be0be8761261428f0aa8ba2657" + } + ) + .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F") + .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F") + .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECF") + }; + } + + public override void PerformTest() + { + DRBGTestVector[] tests = createTestVectorData(); + SP80090Drbg d; + DRBGTestVector tv; + byte[] output; + + for (int i = 0; i != tests.Length; i++) + { + tv = tests[i]; + + byte[] nonce = tv.nonce(); + byte[] personalisationString = tv.personalizationString(); + + d = new CtrSP800Drbg(tv.getCipher(), tv.keySizeInBits(), tv.securityStrength(), tv.entropySource(), personalisationString, nonce); + + output = new byte[tv.expectedValue(0).Length]; + + d.Generate(output, tv.additionalInput(0), tv.predictionResistance()); + + byte[] expected = tv.expectedValue(0); + + if (!AreEqual(expected, output)) + { + Fail("Test #" + (i + 1) + ".1 failed, expected " + Hex.ToHexString(tv.expectedValue(0)) + " got " + Hex.ToHexString(output)); + } + + output = new byte[tv.expectedValue(0).Length]; + + d.Generate(output, tv.additionalInput(1), tv.predictionResistance()); + + expected = tv.expectedValue(1); + if (!AreEqual(expected, output)) + { + Fail("Test #" + (i + 1) + ".2 failed, expected " + Hex.ToHexString(tv.expectedValue(1)) + " got " + Hex.ToHexString(output)); + } + } + + // DESede/TDEA key parity test + tv = tests[0]; + + SP80090Drbg drbg = new CtrSP800Drbg(new KeyParityCipher(tv.getCipher()), tv.keySizeInBits(), tv.securityStrength(), tv.entropySource(), tv.personalizationString(), tv.nonce()); + + output = new byte[tv.expectedValue(0).Length]; + + drbg.Generate(output, tv.additionalInput(0), tv.predictionResistance()); + + // Exception tests + try + { + d = new CtrSP800Drbg(new AesEngine(), 256, 256, new Bit232EntropyProvider().Get(128), null, null); + Fail("no exception thrown"); + } + catch (ArgumentException e) + { + if (!e.Message.Equals("Not enough entropy for security strength required")) + { + Fail("Wrong exception", e); + } + } + + try + { + d = new CtrSP800Drbg(new DesEdeEngine(), 256, 256, new Bit232EntropyProvider().Get(232), null, null); + Fail("no exception thrown"); + } + catch (ArgumentException e) + { + if (!e.Message.Equals("Requested security strength is not supported by block cipher and key size")) + { + Fail("Wrong exception", e); + } + } + + try + { + d = new CtrSP800Drbg(new DesEdeEngine(), 168, 256, new Bit232EntropyProvider().Get(232), null, null); + Fail("no exception thrown"); + } + catch (ArgumentException e) + { + if (!e.Message.Equals("Requested security strength is not supported by block cipher and key size")) + { + Fail("Wrong exception", e); + } + } + + try + { + d = new CtrSP800Drbg(new AesEngine(), 192, 256, new Bit232EntropyProvider().Get(232), null, null); + Fail("no exception thrown"); + } + catch (ArgumentException e) + { + if (!e.Message.Equals("Requested security strength is not supported by block cipher and key size")) + { + Fail("Wrong exception", e); + } + } + } + + internal class Bit232EntropyProvider : TestEntropySourceProvider + { + internal Bit232EntropyProvider() : base(Hex.Decode( + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C" + + "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C" + + "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDC"), true) + { } + } + + internal class Bit256EntropyProvider : TestEntropySourceProvider + { + internal Bit256EntropyProvider(): base(Hex.Decode( + "0001020304050607" + + "08090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F" + + "8081828384858687" + + "88898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F" + + "C0C1C2C3C4C5C6C7" + + "C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF"), true) + { } + } + + internal class Bit320EntropyProvider : TestEntropySourceProvider + { + internal Bit320EntropyProvider() : base(Hex.Decode( + "000102030405060708090A0B0C0D0E0F" + + "101112131415161718191A1B1C1D1E1F2021222324252627" + + "808182838485868788898A8B8C8D8E8F" + + "909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7" + + "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF" + + "D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7"), true) + { } + } + + internal class Bit384EntropyProvider : TestEntropySourceProvider + { + internal Bit384EntropyProvider() : base(Hex.Decode( + "000102030405060708090A0B0C0D0E0F1011121314151617" + + "18191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F" + + "808182838485868788898A8B8C8D8E8F9091929394959697" + + "98999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAF" + + "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7" + + "D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF"), true) + { } + } + + internal class KeyParityCipher : IBlockCipher + { + private IBlockCipher cipher; + + internal KeyParityCipher(IBlockCipher cipher) + { + this.cipher = cipher; + } + + public void Init(bool forEncryption, ICipherParameters parameters) + { + byte[] k = Arrays.Clone(((KeyParameter)parameters).GetKey()); + + DesEdeParameters.SetOddParity(k); + + if (!Arrays.AreEqual(((KeyParameter)parameters).GetKey(), k)) + { + throw new ArgumentException("key not odd parity"); + } + + cipher.Init(forEncryption, parameters); + } + + public String AlgorithmName + { + get + { + return cipher.AlgorithmName; + } + } + + public bool IsPartialBlockOkay + { + get + { + return false; + } + } + + public int GetBlockSize() + { + return cipher.GetBlockSize(); + } + + public int ProcessBlock(byte[] input, int inOff, byte[] output, int outOff) + { + return cipher.ProcessBlock(input, inOff, output, outOff); + } + + public void Reset() + { + cipher.Reset(); + } + } + + } + +} diff --git a/crypto/test/src/crypto/prng/test/DRGBTestVector.cs b/crypto/test/src/crypto/prng/test/DRGBTestVector.cs new file mode 100644 index 000000000..a4129b9f8 --- /dev/null +++ b/crypto/test/src/crypto/prng/test/DRGBTestVector.cs @@ -0,0 +1,129 @@ +using Org.BouncyCastle.Utilities.Encoders; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Org.BouncyCastle.Crypto.Prng.Test +{ + public class DRBGTestVector + { + private IDigest _digest; + private IBlockCipher _cipher; + private int _keySizeInBits; + private IEntropySource _eSource; + private bool _pr; + private String _nonce; + private String _personalisation; + private int _ss; + private String[] _ev; + private List _ai = new List(); + + public DRBGTestVector(IDigest digest, IEntropySource eSource, bool predictionResistance, String nonce, int securityStrength, String[] expected) + { + _digest = digest; + _eSource = eSource; + _pr = predictionResistance; + _nonce = nonce; + _ss = securityStrength; + _ev = expected; + _personalisation = null; + } + + public DRBGTestVector(IBlockCipher cipher, int keySizeInBits, IEntropySource eSource, bool predictionResistance, String nonce, int securityStrength, String[] expected) + { + _cipher = cipher; + _keySizeInBits = keySizeInBits; + _eSource = eSource; + _pr = predictionResistance; + _nonce = nonce; + _ss = securityStrength; + _ev = expected; + _personalisation = null; + } + + public IDigest getDigest() + { + return _digest; + } + + public IBlockCipher getCipher() + { + return _cipher; + } + + public int keySizeInBits() + { + return _keySizeInBits; + } + + public DRBGTestVector addAdditionalInput(String input) + { + _ai.Add(input); + + return this; + } + + public DRBGTestVector setPersonalizationString(String p) + { + _personalisation = p; + + return this; + } + + public IEntropySource entropySource() + { + return _eSource; + } + + public bool predictionResistance() + { + return _pr; + } + + public byte[] nonce() + { + if (_nonce == null) + { + return null; + } + + return Hex.Decode(_nonce); + } + + public byte[] personalizationString() + { + if (_personalisation == null) + { + return null; + } + + return Hex.Decode(_personalisation); + } + + public int securityStrength() + { + return _ss; + } + + public byte[] expectedValue(int index) + { + return Hex.Decode(_ev[index]); + } + + public byte[] additionalInput(int position) + { + int len = _ai.Count; + byte[] rv; + if (position >= len) + { + rv = null; + } + else + { + rv = Hex.Decode((string)(_ai[position])); + } + return rv; + } + + } +} diff --git a/crypto/test/src/crypto/prng/test/HMacDrbgTest.cs b/crypto/test/src/crypto/prng/test/HMacDrbgTest.cs new file mode 100644 index 000000000..b8d383663 --- /dev/null +++ b/crypto/test/src/crypto/prng/test/HMacDrbgTest.cs @@ -0,0 +1,511 @@ + +using System; + +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Crypto.Prng.Drbg; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.Utilities.Encoders; +using NUnit.Framework; + +namespace Org.BouncyCastle.Crypto.Prng.Test +{ + /** + * HMAC SP800-90 DRBG + */ + [TestFixture] + public class HMacDrbgTest : SimpleTest + { + public override String Name + { + get + { + return "HMacDRBG"; + } + } + + public static void main(String[] args) + { + RunTest(new HMacDrbgTest()); + } + + [Test] + public void HMacDrbgTestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + + private DRBGTestVector[] createTestVectorData() + { + return new DRBGTestVector[] + { + new DRBGTestVector( + new Sha1Digest(), + new SHA1EntropyProvider().Get(440), + false, + "2021222324", + 80, + new String[] + { + "5A7D3B449F481CB38DF79AD2B1FCC01E57F8135E8C0B22CD0630BFB0127FB5408C8EFC17A929896E", + "82cf772ec3e84b00fc74f5df104efbfb2428554e9ce367d03aeade37827fa8e9cb6a08196115d948" + }), + new DRBGTestVector( + new Sha1Digest(), + new SHA1EntropyProvider().Get(440), + false, + "2021222324", + 80, + new String[] + { + "B3BD05246CBA12A64735A4E3FDE599BC1BE30F439BD060208EEA7D71F9D123DF47B3CE069D98EDE6", + "B5DADA380E2872DF935BCA55B882C8C9376902AB639765472B71ACEBE2EA8B1B6B49629CB67317E0" + }) + .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F70717273747576"), + new DRBGTestVector( + new Sha1Digest(), + new SHA1EntropyProvider().Get(440), + false, + "2021222324", + 80, + new String[] + { + "C7AAAC583C6EF6300714C2CC5D06C148CFFB40449AD0BB26FAC0497B5C57E161E36681BCC930CE80", + "6EBD2B7B5E0A2AD7A24B1BF9A1DBA47D43271719B9C37B7FE81BA94045A14A7CB514B446666EA5A7" + }) + .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F90919293949596") + .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6"), + new DRBGTestVector( + new Sha1Digest(), + new SHA1EntropyProvider().Get(440), + true, + "2021222324", + 80, + new String[] + { + "FEC4597F06A3A8CC8529D59557B9E661053809C0BC0EFC282ABD87605CC90CBA9B8633DCB1DAE02E", + "84ADD5E2D2041C01723A4DE4335B13EFDF16B0E51A0AD39BD15E862E644F31E4A2D7D843E57C5968" + }), + new DRBGTestVector( + new Sha1Digest(), + new SHA1EntropyProvider().Get(440), + true, + "2021222324", + 80, + new String[] + { + "6C37FDD729AA40F80BC6AB08CA7CC649794F6998B57081E4220F22C5C283E2C91B8E305AB869C625", + "CAF57DCFEA393B9236BF691FA456FEA7FDF1DF8361482CA54D5FA723F4C88B4FA504BF03277FA783" + }) + .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F70717273747576"), + new DRBGTestVector( + new Sha1Digest(), + new SHA1EntropyProvider().Get(440), + true, + "2021222324", + 80, + new String[] + { + "A1BA8FA58BB5013F43F7B6ED52B4539FA16DC77957AEE815B9C07004C7E992EB8C7E591964AFEEA2", + "84264A73A818C95C2F424B37D3CC990B046FB50C2DC64A164211889A010F2471A0912FFEA1BF0195" + }) + .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F90919293949596") + .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6"), + new DRBGTestVector( + new Sha256Digest(), + new SHA256EntropyProvider().Get(440), + false, + "2021222324252627", + 128, + new String[] + { + "D67B8C1734F46FA3F763CF57C6F9F4F2" + + "DC1089BD8BC1F6F023950BFC5617635208C8501238AD7A44" + + "00DEFEE46C640B61AF77C2D1A3BFAA90EDE5D207406E5403", + "8FDAEC20F8B421407059E3588920DA7E" + + "DA9DCE3CF8274DFA1C59C108C1D0AA9B0FA38DA5C792037C" + + "4D33CD070CA7CD0C5608DBA8B885654639DE2187B74CB263" + }), + new DRBGTestVector( + new Sha256Digest(), + new SHA256EntropyProvider().Get(440), + true, + "2021222324252627", + 128, + new String[] + { + "FABD0AE25C69DC2EFDEFB7F20C5A31B5" + + "7AC938AB771AA19BF8F5F1468F665C938C9A1A5DF0628A56" + + "90F15A1AD8A613F31BBD65EEAD5457D5D26947F29FE91AA7", + "6BD925B0E1C232EFD67CCD84F722E927" + + "ECB46AB2B740014777AF14BA0BBF53A45BDBB62B3F7D0B9C" + + "8EEAD057C0EC754EF8B53E60A1F434F05946A8B686AFBC7A" + }), + new DRBGTestVector( + new Sha384Digest(), + new SHA384EntropyProvider().Get(888), + false, + "202122232425262728292A2B", + 192, + new String[]{ + "03AB8BCE4D1DBBB636C5C5B7E1C58499FEB1C619CDD11D35" + + "CD6CF6BB8F20EF27B6F5F9054FF900DB9EBF7BF30ED4DCBB" + + "BC8D5B51C965EA226FFEE2CA5AB2EFD00754DC32F357BF7A" + + "E42275E0F7704DC44E50A5220AD05AB698A22640AC634829", + "B907E77144FD55A54E9BA1A6A0EED0AAC780020C41A15DD8" + + "9A6C163830BA1D094E6A17100FF71EE30A96E1EE04D2A966" + + "03832A4E404F1966C2B5F4CB61B9927E8D12AC1E1A24CF23" + + "88C14E8EC96C35181EAEE32AAA46330DEAAFE5E7CE783C74"}) + .setPersonalizationString( + "404142434445464748494A4B4C4D4E" + + "4F505152535455565758595A5B5C5D5E5F60616263646566" + + "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" + + "7F808182838485868788898A8B8C8D8E8F90919293949596" + + "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"), + new DRBGTestVector( + new Sha384Digest(), + new SHA384EntropyProvider().Get(888), + true, + "202122232425262728292A2B", + 192, + new String[]{ + "804A3AD720F4FCE8738D0632514FEF16430CB7D63A8DF1A5" + + "F02A3CE3BD7ED6A668B69E63E2BB93F096EE753D6194A0F1" + + "A32711063653009636337D22167CC4402D019AC216FA574F" + + "091CF6EA283568D737A77BE38E8F09382C69E76B142ABC3A", + "73B8E55C753202176A17B9B9754A9FE6F23B01861FCD4059" + + "6AEAA301AF1AEF8AF0EAF22FBF34541EFFAB1431666ACACC" + + "759338C7E28672819D53CFEF10A3E19DAFBD53295F1980A9" + + "F491504A2725506784B7AC826D92C838A8668171CAAA86E7"}) + .setPersonalizationString( + "404142434445464748494A4B4C4D4E" + + "4F505152535455565758595A5B5C5D5E5F60616263646566" + + "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" + + "7F808182838485868788898A8B8C8D8E8F90919293949596" + + "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"), + new DRBGTestVector( + new Sha512Digest(), + new SHA512EntropyProvider().Get(888), + false, + "202122232425262728292A2B2C2D2E2F", + 256, + new String[]{ + "2A5FF6520C20F66E" + + "D5EA431BD4AEAC58F975EEC9A015137D5C94B73AA09CB8B5" + + "9D611DDEECEB34A52BB999424009EB9EAC5353F92A6699D2" + + "0A02164EEBBC6492941E10426323898465DFD731C7E04730" + + "60A5AA8973841FDF3446FB6E72A58DA8BDA2A57A36F3DD98" + + "6DF85C8A5C6FF31CDE660BF8A841B21DD6AA9D3AC356B87B", + "0EDC8D7D7CEEC7FE" + + "36333FB30C0A9A4B27AA0BECBF075568B006C1C3693B1C29" + + "0F84769C213F98EB5880909EDF068FDA6BFC43503987BBBD" + + "4FC23AFBE982FE4B4B007910CC4874EEC217405421C8D8A1" + + "BA87EC684D0AF9A6101D9DB787AE82C3A6A25ED478DF1B12" + + "212CEC325466F3AC7C48A56166DD0B119C8673A1A9D54F67"}) + .setPersonalizationString( + "404142434445464748494A4B4C4D4E" + + "4F505152535455565758595A5B5C5D5E5F60616263646566" + + "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" + + "7F808182838485868788898A8B8C8D8E8F90919293949596" + + "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"), + new DRBGTestVector( + new Sha512Digest(), + new SHA512EntropyProvider().Get(888), + true, + "202122232425262728292A2B2C2D2E2F", + 256, + new String[]{ + "AAE4DC3C9ECC74D9" + + "061DD527117EF3D29E1E52B26853C539D6CA797E8DA3D0BB" + + "171D8E30B8B194D8C28F7F6BE3B986B88506DC6A01B294A7" + + "165DD1C3470F7BE7B396AA0DB7D50C4051E7C7E1C8A7D21A" + + "2B5878C0BCB163CAA79366E7A1162FDC88429616CD3E6977" + + "8D327520A6BBBF71D8AA2E03EC4A9DAA0E77CF93E1EE30D2 ", + "129FF6D31A23FFBC" + + "870632B35EE477C2280DDD2ECDABEDB900C78418BE2D243B" + + "B9D8E5093ECE7B6BF48638D8F704D134ADDEB7F4E9D5C142" + + "CD05683E72B516486AF24AEC15D61E81E270DD4EBED91B62" + + "12EB8896A6250D5C8BC3A4A12F7E3068FBDF856F47EB23D3" + + "79F82C1EBCD1585FB260B9C0C42625FBCEE68CAD773CD5B1"}) + .setPersonalizationString( + "404142434445464748494A4B4C4D4E" + + "4F505152535455565758595A5B5C5D5E5F60616263646566" + + "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" + + "7F808182838485868788898A8B8C8D8E8F90919293949596" + + "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"), + new DRBGTestVector( + new Sha512Digest(), + new SHA512EntropyProvider().Get(888), + false, + "202122232425262728292A2B2C2D2E2F", + 256, + new String[]{ + "7AE31A2DEC31075F" + + "E5972660C16D22ECC0D415C5693001BE5A468B590BC1AE2C" + + "43F647F8D681AEEA0D87B79B0B4E5D089CA2C9D327534234" + + "0254E6B04690D77A71A294DA9568479EEF8BB2A2110F18B6" + + "22F60F35235DE0E8F9D7E98105D84AA24AF0757AF005DFD5" + + "2FA51DE3F44FCE0C5F3A27FCE8B0F6E4A3F7C7B53CE34A3D", + "D83A8084630F286D" + + "A4DB49B9F6F608C8993F7F1397EA0D6F4A72CF3EF2733A11" + + "AB823C29F2EBDEC3EDE962F93D920A1DB59C84E1E879C29F" + + "5F9995FC3A6A3AF9B587CA7C13EA197D423E81E1D6469942" + + "B6E2CA83A97E91F6B298266AC148A1809776C26AF5E239A5" + + "5A2BEB9E752203A694E1F3FE2B3E6A0C9C314421CDB55FBD "}) + .setPersonalizationString( + "404142434445464748494A4B4C4D4E" + + "4F505152535455565758595A5B5C5D5E5F60616263646566" + + "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" + + "7F808182838485868788898A8B8C8D8E8F90919293949596" + + "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE") + .addAdditionalInput( + "606162636465666768696A6B6C6D6E" + + "6F707172737475767778797A7B7C7D7E7F80818283848586" + + "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" + + "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" + + "B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCE") + .addAdditionalInput( + "A0A1A2A3A4A5A6A7A8A9AAABACADAE" + + "AFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6" + + "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" + + "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6" + + "F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E"), + new DRBGTestVector( + new Sha512Digest(), + new SHA512EntropyProvider().Get(888), + true, + "202122232425262728292A2B2C2D2E2F", + 256, + new String[]{ + "28FD6060C4F35F4D" + + "317AB2060EE32019E0DAA330F3F5650BBCA57CB67EE6AF1C" + + "6F25D1B01F3601EDA85DC2ED29A9B2BA4C85CF491CE7185F" + + "1A2BD9378AE3C655BD1CEC2EE108AE7FC382989F6D4FEA8A" + + "B01499697C2F07945CE02C5ED617D04287FEAF3BA638A4CE" + + "F3BB6B827E40AF16279580FCF1FDAD830930F7FDE341E2AF", + "C0B1601AFE39338B" + + "58DC2BE7C256AEBE3C21C5A939BEEC7E97B3528AC420F0C6" + + "341847187666E0FF578A8EB0A37809F877365A28DF2FA0F0" + + "6354A6F02496747369375B9A9D6B756FDC4A8FB308E08256" + + "9D79A85BB960F747256626389A3B45B0ABE7ECBC39D5CD7B" + + "2C18DF2E5FDE8C9B8D43474C54B6F9839468445929B438C7"}), + new DRBGTestVector( + new Sha512Digest(), + new SHA512EntropyProvider().Get(888), + true, + "202122232425262728292A2B2C2D2E2F", + 256, + new String[]{ + "72691D2103FB567C" + + "CD30370715B36666F63430087B1C688281CA0974DB456BDB" + + "A7EB5C48CFF62EA05F9508F3B530CE995A272B11EC079C13" + + "923EEF8E011A93C19B58CC6716BC7CB8BD886CAA60C14D85" + + "C023348BD77738C475D6C7E1D9BFF4B12C43D8CC73F838DC" + + "4F8BD476CF8328EEB71B3D873D6B7B859C9B21065638FF95", + "8570DA3D47E1E160" + + "5CF3E44B8D328B995EFC64107B6292D1B1036B5F88CE3160" + + "2F12BEB71D801C0942E7C0864B3DB67A9356DB203490D881" + + "24FE86BCE38AC2269B4FDA6ABAA884039DF80A0336A24D79" + + "1EB3067C8F5F0CF0F18DD73B66A7B316FB19E02835CC6293" + + "65FCD1D3BE640178ED9093B91B36E1D68135F2785BFF505C"}) + .addAdditionalInput( + "606162636465666768696A6B6C6D6E" + + "6F707172737475767778797A7B7C7D7E7F80818283848586" + + "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" + + "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" + + "B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCE") + .addAdditionalInput( + "A0A1A2A3A4A5A6A7A8A9AAABACADAE" + + "AFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6" + + "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" + + "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6" + + "F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E"), + new DRBGTestVector( + new Sha512Digest(), + new SHA512EntropyProvider().Get(888), + true, + "202122232425262728292A2B2C2D2E2F", + 256, + new String[]{ + "AAE4DC3C9ECC74D9" + + "061DD527117EF3D29E1E52B26853C539D6CA797E8DA3D0BB" + + "171D8E30B8B194D8C28F7F6BE3B986B88506DC6A01B294A7" + + "165DD1C3470F7BE7B396AA0DB7D50C4051E7C7E1C8A7D21A" + + "2B5878C0BCB163CAA79366E7A1162FDC88429616CD3E6977" + + "8D327520A6BBBF71D8AA2E03EC4A9DAA0E77CF93E1EE30D2 ", + "129FF6D31A23FFBC" + + "870632B35EE477C2280DDD2ECDABEDB900C78418BE2D243B" + + "B9D8E5093ECE7B6BF48638D8F704D134ADDEB7F4E9D5C142" + + "CD05683E72B516486AF24AEC15D61E81E270DD4EBED91B62" + + "12EB8896A6250D5C8BC3A4A12F7E3068FBDF856F47EB23D3" + + "79F82C1EBCD1585FB260B9C0C42625FBCEE68CAD773CD5B1"}) + .setPersonalizationString( + "404142434445464748494A4B4C4D4E" + + "4F505152535455565758595A5B5C5D5E5F60616263646566" + + "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" + + "7F808182838485868788898A8B8C8D8E8F90919293949596" + + "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"), + new DRBGTestVector( + new Sha512Digest(), + new SHA512EntropyProvider().Get(888), + true, + "202122232425262728292A2B2C2D2E2F", + 256, + new String[]{ + "B8E827652175E6E0" + + "6E513C7BE94B5810C14ED94AD903647940CAEB7EE014C848" + + "8DCBBE6D4D6616D06656A3DC707CDAC4F02EE6D8408C065F" + + "CB068C0760DA47C5D60E5D70D09DC3929B6979615D117F7B" + + "EDCC661A98514B3A1F55B2CBABDCA59F11823E4838065F1F" + + "8431CBF28A577738234AF3F188C7190CC19739E72E9BBFFF", + "7ED41B9CFDC8C256" + + "83BBB4C553CC2DC61F690E62ABC9F038A16B8C519690CABE" + + "BD1B5C196C57CF759BB9871BE0C163A57315EA96F615136D" + + "064572F09F26D659D24211F9610FFCDFFDA8CE23FFA96735" + + "7595182660877766035EED800B05364CE324A75EB63FD9B3" + + "EED956D147480B1D0A42DF8AA990BB628666F6F61D60CBE2"}) + .setPersonalizationString( + "404142434445464748494A4B4C4D4E" + + "4F505152535455565758595A5B5C5D5E5F60616263646566" + + "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" + + "7F808182838485868788898A8B8C8D8E8F90919293949596" + + "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE") + .addAdditionalInput( + "606162636465666768696A6B6C6D6E" + + "6F707172737475767778797A7B7C7D7E7F80818283848586" + + "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" + + "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" + + "B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCE") + .addAdditionalInput( + "A0A1A2A3A4A5A6A7A8A9AAABACADAE" + + "AFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6" + + "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" + + "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6" + + "F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E") + }; + } + + public override void PerformTest() + { + DRBGTestVector[] tests = createTestVectorData(); + SP80090Drbg d; + + for (int i = 0; i != tests.Length; i++) + { + DRBGTestVector tv = tests[i]; + + byte[] nonce = tv.nonce(); + byte[] personalisationString = tv.personalizationString(); + + d = new HMacSP800Drbg(new HMac(tv.getDigest()), tv.securityStrength(), tv.entropySource(), personalisationString, nonce); + + byte[] output = new byte[tv.expectedValue(0).Length]; + + d.Generate(output, tv.additionalInput(0), tv.predictionResistance()); + + byte[] expected = tv.expectedValue(0); + + if (!AreEqual(expected, output)) + { + Fail("Test #" + (i + 1) + ".1 failed, expected " + Hex.ToHexString(tv.expectedValue(0)) + " got " + Hex.ToHexString(output)); + } + + output = new byte[tv.expectedValue(0).Length]; + + d.Generate(output, tv.additionalInput(1), tv.predictionResistance()); + + expected = tv.expectedValue(1); + if (!AreEqual(expected, output)) + { + Fail("Test #" + (i + 1) + ".2 failed, expected " + Hex.ToHexString(tv.expectedValue(1)) + " got " + Hex.ToHexString(output)); + } + } + + // Exception tests + // + try + { + d = new HMacSP800Drbg(new HMac(new Sha256Digest()), 256, new SHA256EntropyProvider().Get(128), null, null); + Fail("no exception thrown"); + } + catch (ArgumentException e) + { + if (!e.Message.Equals("Not enough entropy for security strength required")) + { + Fail("Wrong exception", e); + } + } + } + + private class SHA1EntropyProvider : TestEntropySourceProvider + { + internal SHA1EntropyProvider() : base( + Hex.Decode( + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F30313233343536" + + "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" + + "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6"), true) + { + } + } + + internal class SHA256EntropyProvider : TestEntropySourceProvider + { + internal SHA256EntropyProvider() : base(Hex.Decode( + "00010203040506" + + "0708090A0B0C0D0E0F101112131415161718191A1B1C1D1E" + + "1F202122232425262728292A2B2C2D2E2F30313233343536" + + "80818283848586" + + "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" + + "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" + + "C0C1C2C3C4C5C6" + + "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" + + "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6"), true) + { + } + } + + internal class SHA384EntropyProvider : TestEntropySourceProvider + { + internal SHA384EntropyProvider() : base(Hex.Decode( + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223242526" + + "2728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F50515253545556" + + "5758595A5B5C5D5E5F606162636465666768696A6B6C6D6E" + + "808182838485868788898A8B8C8D8E" + + "8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6" + + "A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBE" + + "BFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6" + + "D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEE" + + "C0C1C2C3C4C5C6C7C8C9CACBCCCDCE" + + "CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6" + + "E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFE" + + "FF000102030405060708090A0B0C0D0E0F10111213141516" + + "1718191A1B1C1D1E1F202122232425262728292A2B2C2D2E"), true) + { } + } + + internal class SHA512EntropyProvider : TestEntropySourceProvider + { + internal SHA512EntropyProvider() : + base(Hex.Decode( + "000102030405060708090A0B0C0D0E" + + "0F101112131415161718191A1B1C1D1E1F20212223242526" + + "2728292A2B2C2D2E2F303132333435363738393A3B3C3D3E" + + "3F404142434445464748494A4B4C4D4E4F50515253545556" + + "5758595A5B5C5D5E5F606162636465666768696A6B6C6D6E" + + "808182838485868788898A8B8C8D8E" + + "8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6" + + "A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBE" + + "BFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6" + + "D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEE" + + "C0C1C2C3C4C5C6C7C8C9CACBCCCDCE" + + "CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6" + + "E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFE" + + "FF000102030405060708090A0B0C0D0E0F10111213141516" + + "1718191A1B1C1D1E1F202122232425262728292A2B2C2D2E"), true) + { + } + } + } +} diff --git a/crypto/test/src/crypto/prng/test/HashDrbgTest.cs b/crypto/test/src/crypto/prng/test/HashDrbgTest.cs new file mode 100644 index 000000000..d9776e0d6 --- /dev/null +++ b/crypto/test/src/crypto/prng/test/HashDrbgTest.cs @@ -0,0 +1,471 @@ +using System; + +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Prng.Drbg; +using Org.BouncyCastle.Utilities.Test; +using Org.BouncyCastle.Utilities.Encoders; +using NUnit.Framework; + +namespace Org.BouncyCastle.Crypto.Prng.Test +{ + /** + * DRBG Test + */ + [TestFixture] + public class HashDrbgTest: SimpleTest + { + public override String Name + { + get + { + return "HashDRBG"; + } + } + + public static void main(String[] args) + { + RunTest(new HashDrbgTest()); + } + + private DRBGTestVector[] createTestVectorData() + { + return new DRBGTestVector[] + { + new DRBGTestVector( + new Sha1Digest(), + new SHA1EntropyProvider().Get(440), + false, + "2021222324", + 80, + new String[] + { + "9F7CFF1ECA23E750F66326969F11800F12088BA68E441D15D888B3FE12BF66FE057494F4546DE2F1", + "B77AA5C0CD55BBCEED7574AF223AFD988C7EEC8EFF4A94E5E89D26A04F58FA79F5E0D3702D7A9A6A" + } + ), + new DRBGTestVector( + new Sha1Digest(), + new SHA1EntropyProvider().Get(440), + false, + "2021222324", + 80, + new String[] + { + "AB438BD3B01A0AF85CFEE29F7D7B71621C4908B909124D430E7B406FB1086EA994C582E0D656D989", + "29D9098F987E7005314A0F51B3DD2B8122F4AED706735DE6AD5DDBF223177C1E5F3AEBC52FAB90B9" + }) + .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F70717273747576"), + new DRBGTestVector( + new Sha1Digest(), + new SHA1EntropyProvider().Get(440), + false, + "2021222324", + 80, + new String[] + { + "E76B4EDD5C865BC8AFD809A59B69B429AC7F4352A579BCF3F75E56249A3491F87C3CA6848B0FAB25", + "6577B6B4F87A93240B199FE51A3B335313683103DECE171E3256FB7E803586CA4E45DD242EB01F70" + }) + .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F90919293949596") + .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6"), + new DRBGTestVector( + new Sha1Digest(), + new SHA1EntropyProvider().Get(440), + true, + "2021222324", + 80, + new String[] + { + "56EF4913373994D5539F4D7D17AFE7448CDF5E72416CC6A71A340059FA0D5AE526B23250C46C0944", + "575B37A2739814F966C63B60A2C4F149CA9ACC84FC4B25493289B085C67B2E30F5F0B99A2C349E2A" + }), + new DRBGTestVector( + new Sha1Digest(), + new SHA1EntropyProvider().Get(440), + true, + "2021222324", + 80, + new String[] + { + "532CA1165DCFF21C55592687639884AF4BC4B057DF8F41DE653AB44E2ADEC7C9303E75ABE277EDBF", + "73C2C67C696D686D0C4DBCEB5C2AF7DDF6F020B6874FAE4390F102117ECAAFF54418529A367005A0" + }) + .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F70717273747576"), + new DRBGTestVector( + new Sha1Digest(), + new SHA1EntropyProvider().Get(440), + true, + "2021222324", + 80, + new String[] + { + "183C242A1430E46C4ED70B4DBE1BF9AB0AB8721CDCA2A2D1820AD6F6C956858543B2AA191D8D1287", + "F196F9BD021C745CBD5AC7BFCE48EAAF0D0E7C091FBF436940E63A198EE770D9A4F0718669AF2BC9" + }) + .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F90919293949596") + .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6"), + new DRBGTestVector( + new Sha256Digest(), + new SHA256EntropyProvider().Get(440), + false, + "2021222324252627", + 128, + new String[] + { + "77E05A0E7DC78AB5D8934D5E93E82C06" + + "A07C04CEE6C9C53045EEB485872777CF3B3E35C474F976B8" + + "94BF301A86FA651F463970E89D4A0534B2ECAD29EC044E7E", + "5FF4BA493C40CFFF3B01E472C575668C" + + "CE3880B9290B05BFEDE5EC96ED5E9B2898508B09BC800EEE" + + "099A3C90602ABD4B1D4F343D497C6055C87BB956D53BF351" + } + ), + new DRBGTestVector( + new Sha256Digest(), + new SHA256EntropyProvider().Get(440), + true, + "2021222324252627", + 128, + new String[] + { + "92275523C70E567BCF9B35EC50B933F8" + + "12616DF586B7F72EE1BC7735A5C2654373CBBC72316DFF84" + + "20A33BF02B97AC8D1952583F270ACD7005CC027F4CF1187E", + "681A46B2AA8694A0FE4DEEA720927A84" + + "EAAA985E59C19F8BE0984D8CBEF8C69B754167641946E040" + + "EE2043E1CCB29DCF063C0A50830E428E6DCA262ECD77C542" + }), + new DRBGTestVector( + new Sha384Digest(), + new SHA384EntropyProvider().Get(888), + false, + "202122232425262728292A2B", + 192, + new String[] + { + "04FF23AD15E78790ADD36B438BBC097C7A11747CC2CCEEDE" + + "2C978B23B3DC63B732C953061D7764990ABFEFC47A581B92" + + "1BC0428C4F12212460E406A0F0651E7F0CB9A90ABFDB07B5" + + "25565C74F0AA085082F6CF213AAFAD0C0646895078F1E1FE", + "4F35B85F95DEE3E873054905CFD02341653E18F529930CBE" + + "14D909F37FEAF2C790D22FAE7516B4590BE35D53E2FE1A35" + + "AFE4B6607CB358589C3B4D094A1D81FE0717F1DF5BDDEB3E" + + "114F130BB781E66C22B5B770E8AE115FF39F8ADAF66DEEDF" + } + ), + new DRBGTestVector( + new Sha384Digest(), + new SHA384EntropyProvider().Get(888), + true, + "202122232425262728292A2B", + 192, + new String[] + { + "97993B78F7C31C0E876DC92EB7D6C408E09D608AD6B99D0E" + + "A2229B05A578C426334FCC8A1C7E676ED2D89A5B4CDF5B3F" + + "4ADF11936BF14F4E10909DBA9C24F4FDFFDE72351DA8E2CC" + + "3B135A395373899E5F1A5955B880CA9B9E9DD4C9CA7FA4D4", + "F5983946320E36C64EF283CA1F65D197CF81624EC6778E77" + + "0E78949D84EF21A45CDD62D1DB76920D4C2836FC6AE5299F" + + "AF1357D9701FAD10FBD88D1E2832239436D76EB271BDC3CA" + + "04425EC88BC0E89A4D5C37FFCE7C6C3ABDE9C413AE6D3FEA" + } + ), + new DRBGTestVector( + new Sha512Digest(), + new SHA512EntropyProvider().Get(888), + false, + "202122232425262728292A2B2C2D2E2F", + 256, + new String[] + { + "DA126CF95C6BF97E" + + "2F731F2137A907ACC70FD7AC9EBACD1C6E31C74029B052E3" + + "AABC48F3B00993F2B2381F7650A55322A968C86E05DE88E6" + + "367F6EF89A601DB4342E9086C7AC13B5E56C32E9E668040B" + + "73847893C5BFD38A1CF44F348B4EEE4CD68ADB7E7B8C837F" + + "19BC4F902761F7CFF24AB1D704FD11C4E929D8553753B55D", + "400B977CE8A2BB6A" + + "84C6FD1CF901459685ABF5408CFF4588CEDF52E2D2DC300A" + + "A9B4FAED8CD0161C2172B1FD269253195883D6EBF21020F2" + + "C20E5F2C81AE60C8595B834A229B1F5B726C1125717E6207" + + "8886EF38E61E32707AD5F8116C6393DFB6E7C7AE0E8E92BB" + + "D7E0C3D04BBA02F5169F2F569A58158915FEE4C9D28D45DB" + } + ) + .setPersonalizationString( + "404142434445464748494A4B4C4D4E" + + "4F505152535455565758595A5B5C5D5E5F60616263646566" + + "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" + + "7F808182838485868788898A8B8C8D8E8F90919293949596" + + "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE") + .addAdditionalInput( + "606162636465666768696A6B6C6D6E" + + "6F707172737475767778797A7B7C7D7E7F80818283848586" + + "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" + + "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" + + "B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCE") + .addAdditionalInput( + "A0A1A2A3A4A5A6A7A8A9AAABACADAE" + + "AFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6" + + "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" + + "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6" + + "F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E"), + new DRBGTestVector( + new Sha512Digest(), + new SHA512EntropyProvider().Get(888), + true, + "202122232425262728292A2B2C2D2E2F", + 256, + new String[] + { + "F93CA6855590A77F" + + "07354097E90E026648B6115DF008FFEDBD9D9811F54E8286" + + "EF00FDD6BA1E58DF2535E3FBDD9A9BA3754A97F36EE83322" + + "1582060A1F37FCE4EE8826636B28EAD589593F4CA8B64738" + + "8F24EB3F0A34796968D21BDEE6F81FD5DF93536F935937B8" + + "025EC8CBF57DDB0C61F2E41463CC1516D657DA2829C6BF90", + "4817618F48C60FB1" + + "CE5BFBDA0CAF4591882A31F6EE3FE0F78779992A06EC60F3" + + "7FB9A8D6108C231F0A927754B0599FA4FA27A4E25E065EF0" + + "3085B892979DC0E7A1080883CAEBFDFD3665A8F2D061C521" + + "F7D6E3DA2AF8B97B6B43B6EC831AF515070A83BBB9AC95ED" + + "4EF49B756A2377A5F0833D847E27A88DDB0C2CE4AD782E7B " + } + ), + new DRBGTestVector( + new Sha512Digest(), + new SHA512EntropyProvider().Get(888), + true, + "202122232425262728292A2B2C2D2E2F", + 256, + new String[] + { + "0455DD4AD7DBACB2" + + "410BE58DF7248D765A4547ABAEE1743B0BCAD37EBD06DA7C" + + "F7CE5E2216E525327E9E2005EBEF2CE53BD733B18128627D" + + "3FD6153089373AF2606A1584646A0EA488BFEF45228699A0" + + "89CEA8AEC44502D86D9591F3552C688B7F7B45FCB0C3C2B9" + + "43C1CD8A6FC63DF4D81C3DA543C9CF2843855EA84E4F959C", + "C047D46D7F614E4E" + + "4A7952C79A451F8F7ACA379967E2977C401C626A2ED70D74" + + "A63660579A354115BC8C8C8CC3AEA3050686A0CFCDB6FA9C" + + "F78D4C2165BAF851C6F9B1CD16A2E14C15C6DAAC56C16E75" + + "FC84A14D58B41622E88B0F1B1995587FD8BAA999CBA98025" + + "4C8AB9A9691DF7B84D88B639A9A3106DEABEB63748B99C09" + } + ) + .addAdditionalInput( + "606162636465666768696A6B6C6D6E" + + "6F707172737475767778797A7B7C7D7E7F80818283848586" + + "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" + + "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" + + "B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCE") + .addAdditionalInput( + "A0A1A2A3A4A5A6A7A8A9AAABACADAE" + + "AFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6" + + "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" + + "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6" + + "F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E"), + new DRBGTestVector( + new Sha512Digest(), + new SHA512EntropyProvider().Get(888), + true, + "202122232425262728292A2B2C2D2E2F", + 256, + new String[] + { + "22EB93A67911DA73" + + "85D9180C78127DE1A04FF713114C07C9C615F7CC5EF72744" + + "A2DDCD7C3CB85E65DED8EF5F240FBDCBEBBDE2BAAC8ECF7D" + + "CBC8AC333E54607AD41DC495D83DF72A05EF55B127C1441C" + + "9A0EFFDA2C7954DB6C2D04342EB812E5E0B11D6C395F41ED" + + "A2702ECE5BA479E2DFA18F953097492636C12FE30CE5C968", + "E66698CFBF1B3F2E" + + "919C03036E584EAA81CF1C6666240AF05F70637043733954" + + "D8A1E5A66A04C53C6900FDC145D4A3A80A31F5868ACE9AC9" + + "4E14E2051F624A05EEA1F8B684AA5410BCE315E76EA07C71" + + "5D6F34731320FF0DCF78D795E6EFA2DF92B98BE636CDFBA2" + + "9008DD392112AEC202F2E481CB9D83F987FEA69CD1B368BB" + } + ) + .setPersonalizationString( + "404142434445464748494A4B4C4D4E" + + "4F505152535455565758595A5B5C5D5E5F60616263646566" + + "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" + + "7F808182838485868788898A8B8C8D8E8F90919293949596" + + "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"), + new DRBGTestVector( + new Sha512Digest(), + new SHA512EntropyProvider().Get(888), + true, + "202122232425262728292A2B2C2D2E2F", + 256, + new String[] + { + "7596A76372308BD5" + + "A5613439934678B35521A94D81ABFE63A21ACF61ABB88B61" + + "E86A12C37F308F2BBBE32BE4B38D03AE808386494D70EF52" + + "E9E1365DD18B7784CAB826F31D47579E4D57F69D8BF3152B" + + "95741946CEBE58571DF58ED39980D9AF44E69F01E8989759" + + "8E40171101A0E3302838E0AD9E849C01988993CF9F6E5263", + "DBE5EE36FCD85301" + + "303E1C3617C1AC5E23C08885D0BEFAAD0C85A0D89F85B9F1" + + "6ECE3D88A24EB96504F2F13EFA7049621782F5DE2C416A0D" + + "294CCFE53545C4E309C48E1E285A2B829A574B72B3C2FBE1" + + "34D01E3706B486F2401B9820E17298A342666918E15B8462" + + "87F8C5AF2D96B20FAF3D0BB392E15F4A06CDB0DECD1B6AD7" + } + ) + .setPersonalizationString( + "404142434445464748494A4B4C4D4E" + + "4F505152535455565758595A5B5C5D5E5F60616263646566" + + "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" + + "7F808182838485868788898A8B8C8D8E8F90919293949596" + + "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE") + .addAdditionalInput( + "606162636465666768696A6B6C6D6E" + + "6F707172737475767778797A7B7C7D7E7F80818283848586" + + "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" + + "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" + + "B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCE") + .addAdditionalInput( + "A0A1A2A3A4A5A6A7A8A9AAABACADAE" + + "AFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6" + + "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" + + "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6" + + "F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E") + }; + } + + public override void PerformTest() + { + DRBGTestVector[] tests = createTestVectorData(); + SP80090Drbg d; + + for (int i = 0; i != tests.Length; i++) + { + DRBGTestVector tv = tests[i]; + + byte[] nonce = tv.nonce(); + byte[] personalisationString = tv.personalizationString(); + + d = new HashSP800Drbg(tv.getDigest(), tv.securityStrength(), tv.entropySource(), personalisationString, nonce); + + byte[] output = new byte[tv.expectedValue(0).Length]; + + d.Generate(output, tv.additionalInput(0), tv.predictionResistance()); + + byte[] expected = tv.expectedValue(0); + + if (!AreEqual(expected, output)) + { + Fail("Test #" + (i + 1) + ".1 failed, expected " + Hex.ToHexString(tv.expectedValue(0)) + " got " + Hex.ToHexString(output)); + } + + output = new byte[tv.expectedValue(0).Length]; + + d.Generate(output, tv.additionalInput(1), tv.predictionResistance()); + + expected = tv.expectedValue(1); + if (!AreEqual(expected, output)) + { + Fail("Test #" + (i + 1) + ".2 failed, expected " + Hex.ToHexString(tv.expectedValue(1)) + " got " + Hex.ToHexString(output)); + } + } + + // Exception tests + // + try + { + d = new HashSP800Drbg(new Sha256Digest(), 256, new SHA256EntropyProvider().Get(128), null, null); + Fail("no exception thrown"); + } + catch (ArgumentException e) + { + if (!e.Message.Equals("Not enough entropy for security strength required")) + { + Fail("Wrong exception", e); + } + } + + try + { + d = new HashSP800Drbg(new Sha1Digest(), 256, new SHA256EntropyProvider().Get(256), null, null); + Fail("no exception thrown"); + } + catch (ArgumentException e) + { + if (!e.Message.Equals("Requested security strength is not supported by the derivation function")) + { + Fail("Wrong exception", e); + } + } + } + + internal class SHA1EntropyProvider: TestEntropySourceProvider + { + internal SHA1EntropyProvider(): base( + Hex.Decode( + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F30313233343536" + + "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" + + "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6"), true) + {} + } + + internal class SHA256EntropyProvider: TestEntropySourceProvider + { + internal SHA256EntropyProvider(): base(Hex.Decode( + "00010203040506" + + "0708090A0B0C0D0E0F101112131415161718191A1B1C1D1E" + + "1F202122232425262728292A2B2C2D2E2F30313233343536" + + "80818283848586" + + "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" + + "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" + + "C0C1C2C3C4C5C6" + + "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" + + "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6"), true) + { } + } + + internal class SHA384EntropyProvider: TestEntropySourceProvider + { + internal SHA384EntropyProvider(): base(Hex.Decode( + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223242526" + + "2728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F50515253545556" + + "5758595A5B5C5D5E5F606162636465666768696A6B6C6D6E" + + "808182838485868788898A8B8C8D8E" + + "8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6" + + "A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBE" + + "BFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6" + + "D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEE" + + "C0C1C2C3C4C5C6C7C8C9CACBCCCDCE" + + "CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6" + + "E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFE" + + "FF000102030405060708090A0B0C0D0E0F10111213141516" + + "1718191A1B1C1D1E1F202122232425262728292A2B2C2D2E"), true) + {} + } + + internal class SHA512EntropyProvider: TestEntropySourceProvider + { + internal SHA512EntropyProvider(): base(Hex.Decode( + "000102030405060708090A0B0C0D0E" + + "0F101112131415161718191A1B1C1D1E1F20212223242526" + + "2728292A2B2C2D2E2F303132333435363738393A3B3C3D3E" + + "3F404142434445464748494A4B4C4D4E4F50515253545556" + + "5758595A5B5C5D5E5F606162636465666768696A6B6C6D6E" + + "808182838485868788898A8B8C8D8E" + + "8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6" + + "A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBE" + + "BFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6" + + "D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEE" + + "C0C1C2C3C4C5C6C7C8C9CACBCCCDCE" + + "CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6" + + "E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFE" + + "FF000102030405060708090A0B0C0D0E0F10111213141516" + + "1718191A1B1C1D1E1F202122232425262728292A2B2C2D2E"), true) + { } + } +} +} diff --git a/crypto/test/src/crypto/prng/test/TestEntropySourceProvider.cs b/crypto/test/src/crypto/prng/test/TestEntropySourceProvider.cs new file mode 100644 index 000000000..a37bcd844 --- /dev/null +++ b/crypto/test/src/crypto/prng/test/TestEntropySourceProvider.cs @@ -0,0 +1,64 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Prng.Test +{ + public class TestEntropySourceProvider: IEntropySourceProvider + { + private readonly byte[] data; + private readonly bool isPredictionResistant; + + internal TestEntropySourceProvider(byte[] data, bool isPredictionResistant) + { + this.data = data; + this.isPredictionResistant = isPredictionResistant; + } + + public IEntropySource Get(int bitsRequired) + { + return new EntropySource(bitsRequired, data, isPredictionResistant); + } + + internal class EntropySource: IEntropySource + { + private readonly int bitsRequired; + private readonly byte[] data; + private readonly bool isPredictionResistant; + + int index = 0; + + internal EntropySource(int bitsRequired, byte[] data, bool isPredictionResistant) + { + this.bitsRequired = bitsRequired; + this.data = data; + this.isPredictionResistant = isPredictionResistant; + } + + public bool IsPredictionResistant + { + get + { + return isPredictionResistant; + } + } + + public byte[] GetEntropy() + { + byte[] rv = new byte[bitsRequired / 8]; + + Array.Copy(data, index, rv, 0, rv.Length); + + index += bitsRequired / 8; + + return rv; + } + + public int EntropySize + { + get + { + return bitsRequired; + } + } + } +} +} -- cgit 1.5.1 From 3585bbfd9ae9c9ce82854c91a1aae61a0d57720c Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 16 Nov 2015 13:28:13 +0700 Subject: More rename/delete --- crypto/src/crypto/prng/ISP80090Drbg.cs | 33 ------ crypto/test/src/crypto/prng/test/DRGBTestVector.cs | 129 --------------------- crypto/test/src/crypto/prng/test/DrbgTestVector.cs | 129 +++++++++++++++++++++ 3 files changed, 129 insertions(+), 162 deletions(-) delete mode 100644 crypto/src/crypto/prng/ISP80090Drbg.cs delete mode 100644 crypto/test/src/crypto/prng/test/DRGBTestVector.cs create mode 100644 crypto/test/src/crypto/prng/test/DrbgTestVector.cs (limited to 'crypto/test/src') diff --git a/crypto/src/crypto/prng/ISP80090Drbg.cs b/crypto/src/crypto/prng/ISP80090Drbg.cs deleted file mode 100644 index c39cf365f..000000000 --- a/crypto/src/crypto/prng/ISP80090Drbg.cs +++ /dev/null @@ -1,33 +0,0 @@ -namespace Org.BouncyCastle.Crypto.Prng.Drbg -{ - /** - * Interface to SP800-90A deterministic random bit generators. - */ - public interface SP80090Drbg - { - /** - * Return the block size of the DRBG. - * - * @return the block size (in bits) produced by each round of the DRBG. - */ - int BlockSize { get; } - - /** - * Populate a passed in array with random data. - * - * @param output output array for generated bits. - * @param additionalInput additional input to be added to the DRBG in this step. - * @param predictionResistant true if a reseed should be forced, false otherwise. - * - * @return number of bits generated, -1 if a reseed required. - */ - int Generate(byte[] output, byte[] additionalInput, bool predictionResistant); - - /** - * Reseed the DRBG. - * - * @param additionalInput additional input to be added to the DRBG in this step. - */ - void Reseed(byte[] additionalInput); - } -} diff --git a/crypto/test/src/crypto/prng/test/DRGBTestVector.cs b/crypto/test/src/crypto/prng/test/DRGBTestVector.cs deleted file mode 100644 index a4129b9f8..000000000 --- a/crypto/test/src/crypto/prng/test/DRGBTestVector.cs +++ /dev/null @@ -1,129 +0,0 @@ -using Org.BouncyCastle.Utilities.Encoders; -using System; -using System.Collections.Generic; -using System.Text; - -namespace Org.BouncyCastle.Crypto.Prng.Test -{ - public class DRBGTestVector - { - private IDigest _digest; - private IBlockCipher _cipher; - private int _keySizeInBits; - private IEntropySource _eSource; - private bool _pr; - private String _nonce; - private String _personalisation; - private int _ss; - private String[] _ev; - private List _ai = new List(); - - public DRBGTestVector(IDigest digest, IEntropySource eSource, bool predictionResistance, String nonce, int securityStrength, String[] expected) - { - _digest = digest; - _eSource = eSource; - _pr = predictionResistance; - _nonce = nonce; - _ss = securityStrength; - _ev = expected; - _personalisation = null; - } - - public DRBGTestVector(IBlockCipher cipher, int keySizeInBits, IEntropySource eSource, bool predictionResistance, String nonce, int securityStrength, String[] expected) - { - _cipher = cipher; - _keySizeInBits = keySizeInBits; - _eSource = eSource; - _pr = predictionResistance; - _nonce = nonce; - _ss = securityStrength; - _ev = expected; - _personalisation = null; - } - - public IDigest getDigest() - { - return _digest; - } - - public IBlockCipher getCipher() - { - return _cipher; - } - - public int keySizeInBits() - { - return _keySizeInBits; - } - - public DRBGTestVector addAdditionalInput(String input) - { - _ai.Add(input); - - return this; - } - - public DRBGTestVector setPersonalizationString(String p) - { - _personalisation = p; - - return this; - } - - public IEntropySource entropySource() - { - return _eSource; - } - - public bool predictionResistance() - { - return _pr; - } - - public byte[] nonce() - { - if (_nonce == null) - { - return null; - } - - return Hex.Decode(_nonce); - } - - public byte[] personalizationString() - { - if (_personalisation == null) - { - return null; - } - - return Hex.Decode(_personalisation); - } - - public int securityStrength() - { - return _ss; - } - - public byte[] expectedValue(int index) - { - return Hex.Decode(_ev[index]); - } - - public byte[] additionalInput(int position) - { - int len = _ai.Count; - byte[] rv; - if (position >= len) - { - rv = null; - } - else - { - rv = Hex.Decode((string)(_ai[position])); - } - return rv; - } - - } -} diff --git a/crypto/test/src/crypto/prng/test/DrbgTestVector.cs b/crypto/test/src/crypto/prng/test/DrbgTestVector.cs new file mode 100644 index 000000000..a4129b9f8 --- /dev/null +++ b/crypto/test/src/crypto/prng/test/DrbgTestVector.cs @@ -0,0 +1,129 @@ +using Org.BouncyCastle.Utilities.Encoders; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Org.BouncyCastle.Crypto.Prng.Test +{ + public class DRBGTestVector + { + private IDigest _digest; + private IBlockCipher _cipher; + private int _keySizeInBits; + private IEntropySource _eSource; + private bool _pr; + private String _nonce; + private String _personalisation; + private int _ss; + private String[] _ev; + private List _ai = new List(); + + public DRBGTestVector(IDigest digest, IEntropySource eSource, bool predictionResistance, String nonce, int securityStrength, String[] expected) + { + _digest = digest; + _eSource = eSource; + _pr = predictionResistance; + _nonce = nonce; + _ss = securityStrength; + _ev = expected; + _personalisation = null; + } + + public DRBGTestVector(IBlockCipher cipher, int keySizeInBits, IEntropySource eSource, bool predictionResistance, String nonce, int securityStrength, String[] expected) + { + _cipher = cipher; + _keySizeInBits = keySizeInBits; + _eSource = eSource; + _pr = predictionResistance; + _nonce = nonce; + _ss = securityStrength; + _ev = expected; + _personalisation = null; + } + + public IDigest getDigest() + { + return _digest; + } + + public IBlockCipher getCipher() + { + return _cipher; + } + + public int keySizeInBits() + { + return _keySizeInBits; + } + + public DRBGTestVector addAdditionalInput(String input) + { + _ai.Add(input); + + return this; + } + + public DRBGTestVector setPersonalizationString(String p) + { + _personalisation = p; + + return this; + } + + public IEntropySource entropySource() + { + return _eSource; + } + + public bool predictionResistance() + { + return _pr; + } + + public byte[] nonce() + { + if (_nonce == null) + { + return null; + } + + return Hex.Decode(_nonce); + } + + public byte[] personalizationString() + { + if (_personalisation == null) + { + return null; + } + + return Hex.Decode(_personalisation); + } + + public int securityStrength() + { + return _ss; + } + + public byte[] expectedValue(int index) + { + return Hex.Decode(_ev[index]); + } + + public byte[] additionalInput(int position) + { + int len = _ai.Count; + byte[] rv; + if (position >= len) + { + rv = null; + } + else + { + rv = Hex.Decode((string)(_ai[position])); + } + return rv; + } + + } +} -- cgit 1.5.1 From 8bda1de4207632587d2df5fbd08797e22d5f8463 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 16 Nov 2015 21:30:04 +0700 Subject: Finish port of latest PRNG/DRBG stuff from Java --- crypto/crypto.csproj | 105 ++++ .../src/crypto/prng/BasicEntropySourceProvider.cs | 70 +++ crypto/src/crypto/prng/IDrbgProvider.cs | 11 + crypto/src/crypto/prng/IEntropySource.cs | 4 +- crypto/src/crypto/prng/IEntropySourceProvider.cs | 4 +- crypto/src/crypto/prng/SP800SecureRandom.cs | 82 +++ crypto/src/crypto/prng/SP800SecureRandomBuilder.cs | 208 ++++++ crypto/src/crypto/prng/X931Rng.cs | 141 +++++ crypto/src/crypto/prng/X931SecureRandom.cs | 72 +++ crypto/src/crypto/prng/X931SecureRandomBuilder.cs | 87 +++ crypto/src/crypto/prng/drbg/CtrSP800Drbg.cs | 275 ++++---- crypto/src/crypto/prng/drbg/DrbgUtilities.cs | 42 +- crypto/src/crypto/prng/drbg/HMacSP800Drbg.cs | 126 ++-- crypto/src/crypto/prng/drbg/HashSP800Drbg.cs | 240 ++++--- crypto/src/crypto/prng/drbg/ISP80090Drbg.cs | 4 +- crypto/src/security/SecureRandom.cs | 35 +- crypto/src/util/Arrays.cs | 64 +- crypto/test/src/crypto/prng/test/CtrDrbgTest.cs | 662 ++++++++++---------- crypto/test/src/crypto/prng/test/DrbgTestVector.cs | 90 ++- crypto/test/src/crypto/prng/test/HMacDrbgTest.cs | 465 +++++++------- crypto/test/src/crypto/prng/test/HashDrbgTest.cs | 696 +++++++++++---------- .../crypto/prng/test/TestEntropySourceProvider.cs | 21 +- crypto/test/src/crypto/prng/test/X931Test.cs | 137 ++++ crypto/test/src/crypto/prng/test/X931TestVector.cs | 55 ++ 24 files changed, 2297 insertions(+), 1399 deletions(-) create mode 100644 crypto/src/crypto/prng/BasicEntropySourceProvider.cs create mode 100644 crypto/src/crypto/prng/IDrbgProvider.cs create mode 100644 crypto/src/crypto/prng/SP800SecureRandom.cs create mode 100644 crypto/src/crypto/prng/SP800SecureRandomBuilder.cs create mode 100644 crypto/src/crypto/prng/X931Rng.cs create mode 100644 crypto/src/crypto/prng/X931SecureRandom.cs create mode 100644 crypto/src/crypto/prng/X931SecureRandomBuilder.cs create mode 100644 crypto/test/src/crypto/prng/test/X931Test.cs create mode 100644 crypto/test/src/crypto/prng/test/X931TestVector.cs (limited to 'crypto/test/src') diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index 28d0b19b3..0c6dba76c 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -4313,6 +4313,11 @@ SubType = "Code" BuildAction = "Compile" /> + + + + + + + + + + + + + + + + + + + + + - /// Base interface describing an entropy source for a DRGB. + /// Base interface describing an entropy source for a DRBG. ///
    public interface IEntropySource { diff --git a/crypto/src/crypto/prng/IEntropySourceProvider.cs b/crypto/src/crypto/prng/IEntropySourceProvider.cs index 990c6497b..643f92ef8 100644 --- a/crypto/src/crypto/prng/IEntropySourceProvider.cs +++ b/crypto/src/crypto/prng/IEntropySourceProvider.cs @@ -1,8 +1,6 @@ using System; -using System.Collections.Generic; -using System.Text; -namespace Org.BouncyCastle.Crypto +namespace Org.BouncyCastle.Crypto.Prng { /// /// Base interface describing a provider of entropy sources. diff --git a/crypto/src/crypto/prng/SP800SecureRandom.cs b/crypto/src/crypto/prng/SP800SecureRandom.cs new file mode 100644 index 000000000..996ba0846 --- /dev/null +++ b/crypto/src/crypto/prng/SP800SecureRandom.cs @@ -0,0 +1,82 @@ +using System; + +using Org.BouncyCastle.Crypto.Prng.Drbg; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Prng +{ + public class SP800SecureRandom + : SecureRandom + { + private readonly IDrbgProvider mDrbgProvider; + private readonly bool mPredictionResistant; + private readonly SecureRandom mRandomSource; + private readonly IEntropySource mEntropySource; + + private ISP80090Drbg mDrbg; + + internal SP800SecureRandom(SecureRandom randomSource, IEntropySource entropySource, IDrbgProvider drbgProvider, bool predictionResistant) + : base((IRandomGenerator)null) + { + this.mRandomSource = randomSource; + this.mEntropySource = entropySource; + this.mDrbgProvider = drbgProvider; + this.mPredictionResistant = predictionResistant; + } + + public override void SetSeed(byte[] seed) + { + lock (this) + { + if (mRandomSource != null) + { + this.mRandomSource.SetSeed(seed); + } + } + } + + public override void SetSeed(long seed) + { + lock (this) + { + // this will happen when SecureRandom() is created + if (mRandomSource != null) + { + this.mRandomSource.SetSeed(seed); + } + } + } + + public override void NextBytes(byte[] bytes) + { + lock (this) + { + if (mDrbg == null) + { + mDrbg = mDrbgProvider.Get(mEntropySource); + } + + // check if a reseed is required... + if (mDrbg.Generate(bytes, null, mPredictionResistant) < 0) + { + mDrbg.Reseed(null); + mDrbg.Generate(bytes, null, mPredictionResistant); + } + } + } + + public override void NextBytes(byte[] buf, int off, int len) + { + byte[] bytes = new byte[len]; + NextBytes(bytes); + Array.Copy(bytes, 0, buf, off, len); + } + + public override byte[] GenerateSeed(int numBytes) + { + byte[] bytes = new byte[numBytes]; + NextBytes(bytes); + return bytes; + } + } +} diff --git a/crypto/src/crypto/prng/SP800SecureRandomBuilder.cs b/crypto/src/crypto/prng/SP800SecureRandomBuilder.cs new file mode 100644 index 000000000..7199f1ae7 --- /dev/null +++ b/crypto/src/crypto/prng/SP800SecureRandomBuilder.cs @@ -0,0 +1,208 @@ +using System; + +using Org.BouncyCastle.Crypto.Prng.Drbg; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Prng +{ + /** + * Builder class for making SecureRandom objects based on SP 800-90A Deterministic Random Bit Generators (DRBG). + */ + public class SP800SecureRandomBuilder + { + private readonly SecureRandom mRandom; + private readonly IEntropySourceProvider mEntropySourceProvider; + + private byte[] mPersonalizationString = null; + private int mSecurityStrength = 256; + private int mEntropyBitsRequired = 256; + + /** + * Basic constructor, creates a builder using an EntropySourceProvider based on the default SecureRandom with + * predictionResistant set to false. + *

    + * Any SecureRandom created from a builder constructed like this will make use of input passed to SecureRandom.setSeed() if + * the default SecureRandom does for its generateSeed() call. + *

    + */ + public SP800SecureRandomBuilder() + : this(new SecureRandom(), false) + { + } + + /** + * Construct a builder with an EntropySourceProvider based on the passed in SecureRandom and the passed in value + * for prediction resistance. + *

    + * Any SecureRandom created from a builder constructed like this will make use of input passed to SecureRandom.setSeed() if + * the passed in SecureRandom does for its generateSeed() call. + *

    + * @param entropySource + * @param predictionResistant + */ + public SP800SecureRandomBuilder(SecureRandom entropySource, bool predictionResistant) + { + this.mRandom = entropySource; + this.mEntropySourceProvider = new BasicEntropySourceProvider(entropySource, predictionResistant); + } + + /** + * Create a builder which makes creates the SecureRandom objects from a specified entropy source provider. + *

    + * Note: If this constructor is used any calls to setSeed() in the resulting SecureRandom will be ignored. + *

    + * @param entropySourceProvider a provider of EntropySource objects. + */ + public SP800SecureRandomBuilder(IEntropySourceProvider entropySourceProvider) + { + this.mRandom = null; + this.mEntropySourceProvider = entropySourceProvider; + } + + /** + * Set the personalization string for DRBG SecureRandoms created by this builder + * @param personalizationString the personalisation string for the underlying DRBG. + * @return the current builder. + */ + public SP800SecureRandomBuilder SetPersonalizationString(byte[] personalizationString) + { + this.mPersonalizationString = personalizationString; + return this; + } + + /** + * Set the security strength required for DRBGs used in building SecureRandom objects. + * + * @param securityStrength the security strength (in bits) + * @return the current builder. + */ + public SP800SecureRandomBuilder SetSecurityStrength(int securityStrength) + { + this.mSecurityStrength = securityStrength; + return this; + } + + /** + * Set the amount of entropy bits required for seeding and reseeding DRBGs used in building SecureRandom objects. + * + * @param entropyBitsRequired the number of bits of entropy to be requested from the entropy source on each seed/reseed. + * @return the current builder. + */ + public SP800SecureRandomBuilder SetEntropyBitsRequired(int entropyBitsRequired) + { + this.mEntropyBitsRequired = entropyBitsRequired; + return this; + } + + /** + * Build a SecureRandom based on a SP 800-90A Hash DRBG. + * + * @param digest digest algorithm to use in the DRBG underneath the SecureRandom. + * @param nonce nonce value to use in DRBG construction. + * @param predictionResistant specify whether the underlying DRBG in the resulting SecureRandom should reseed on each request for bytes. + * @return a SecureRandom supported by a Hash DRBG. + */ + public SP800SecureRandom BuildHash(IDigest digest, byte[] nonce, bool predictionResistant) + { + return new SP800SecureRandom(mRandom, mEntropySourceProvider.Get(mEntropyBitsRequired), + new HashDrbgProvider(digest, nonce, mPersonalizationString, mSecurityStrength), predictionResistant); + } + + /** + * Build a SecureRandom based on a SP 800-90A CTR DRBG. + * + * @param cipher the block cipher to base the DRBG on. + * @param keySizeInBits key size in bits to be used with the block cipher. + * @param nonce nonce value to use in DRBG construction. + * @param predictionResistant specify whether the underlying DRBG in the resulting SecureRandom should reseed on each request for bytes. + * @return a SecureRandom supported by a CTR DRBG. + */ + public SP800SecureRandom BuildCtr(IBlockCipher cipher, int keySizeInBits, byte[] nonce, bool predictionResistant) + { + return new SP800SecureRandom(mRandom, mEntropySourceProvider.Get(mEntropyBitsRequired), + new CtrDrbgProvider(cipher, keySizeInBits, nonce, mPersonalizationString, mSecurityStrength), predictionResistant); + } + + /** + * Build a SecureRandom based on a SP 800-90A HMAC DRBG. + * + * @param hMac HMAC algorithm to use in the DRBG underneath the SecureRandom. + * @param nonce nonce value to use in DRBG construction. + * @param predictionResistant specify whether the underlying DRBG in the resulting SecureRandom should reseed on each request for bytes. + * @return a SecureRandom supported by a HMAC DRBG. + */ + public SP800SecureRandom BuildHMac(IMac hMac, byte[] nonce, bool predictionResistant) + { + return new SP800SecureRandom(mRandom, mEntropySourceProvider.Get(mEntropyBitsRequired), + new HMacDrbgProvider(hMac, nonce, mPersonalizationString, mSecurityStrength), predictionResistant); + } + + private class HashDrbgProvider + : IDrbgProvider + { + private readonly IDigest mDigest; + private readonly byte[] mNonce; + private readonly byte[] mPersonalizationString; + private readonly int mSecurityStrength; + + public HashDrbgProvider(IDigest digest, byte[] nonce, byte[] personalizationString, int securityStrength) + { + this.mDigest = digest; + this.mNonce = nonce; + this.mPersonalizationString = personalizationString; + this.mSecurityStrength = securityStrength; + } + + public ISP80090Drbg Get(IEntropySource entropySource) + { + return new HashSP800Drbg(mDigest, mSecurityStrength, entropySource, mPersonalizationString, mNonce); + } + } + + private class HMacDrbgProvider + : IDrbgProvider + { + private readonly IMac mHMac; + private readonly byte[] mNonce; + private readonly byte[] mPersonalizationString; + private readonly int mSecurityStrength; + + public HMacDrbgProvider(IMac hMac, byte[] nonce, byte[] personalizationString, int securityStrength) + { + this.mHMac = hMac; + this.mNonce = nonce; + this.mPersonalizationString = personalizationString; + this.mSecurityStrength = securityStrength; + } + + public ISP80090Drbg Get(IEntropySource entropySource) + { + return new HMacSP800Drbg(mHMac, mSecurityStrength, entropySource, mPersonalizationString, mNonce); + } + } + + private class CtrDrbgProvider + : IDrbgProvider + { + private readonly IBlockCipher mBlockCipher; + private readonly int mKeySizeInBits; + private readonly byte[] mNonce; + private readonly byte[] mPersonalizationString; + private readonly int mSecurityStrength; + + public CtrDrbgProvider(IBlockCipher blockCipher, int keySizeInBits, byte[] nonce, byte[] personalizationString, int securityStrength) + { + this.mBlockCipher = blockCipher; + this.mKeySizeInBits = keySizeInBits; + this.mNonce = nonce; + this.mPersonalizationString = personalizationString; + this.mSecurityStrength = securityStrength; + } + + public ISP80090Drbg Get(IEntropySource entropySource) + { + return new CtrSP800Drbg(mBlockCipher, mKeySizeInBits, mSecurityStrength, entropySource, mPersonalizationString, mNonce); + } + } + } +} diff --git a/crypto/src/crypto/prng/X931Rng.cs b/crypto/src/crypto/prng/X931Rng.cs new file mode 100644 index 000000000..d09cc6618 --- /dev/null +++ b/crypto/src/crypto/prng/X931Rng.cs @@ -0,0 +1,141 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Prng +{ + internal class X931Rng + { + private const long BLOCK64_RESEED_MAX = 1L << (16 - 1); + private const long BLOCK128_RESEED_MAX = 1L << (24 - 1); + private const int BLOCK64_MAX_BITS_REQUEST = 1 << (13 - 1); + private const int BLOCK128_MAX_BITS_REQUEST = 1 << (19 - 1); + + private readonly IBlockCipher mEngine; + private readonly IEntropySource mEntropySource; + + private readonly byte[] mDT; + private readonly byte[] mI; + private readonly byte[] mR; + + private byte[] mV; + + private long mReseedCounter = 1; + + /** + * + * @param engine + * @param entropySource + */ + internal X931Rng(IBlockCipher engine, byte[] dateTimeVector, IEntropySource entropySource) + { + this.mEngine = engine; + this.mEntropySource = entropySource; + + this.mDT = new byte[engine.GetBlockSize()]; + + Array.Copy(dateTimeVector, 0, mDT, 0, mDT.Length); + + this.mI = new byte[engine.GetBlockSize()]; + this.mR = new byte[engine.GetBlockSize()]; + } + + /** + * Populate a passed in array with random data. + * + * @param output output array for generated bits. + * @param predictionResistant true if a reseed should be forced, false otherwise. + * + * @return number of bits generated, -1 if a reseed required. + */ + internal int Generate(byte[] output, bool predictionResistant) + { + if (mR.Length == 8) // 64 bit block size + { + if (mReseedCounter > BLOCK64_RESEED_MAX) + return -1; + + if (IsTooLarge(output, BLOCK64_MAX_BITS_REQUEST / 8)) + throw new ArgumentException("Number of bits per request limited to " + BLOCK64_MAX_BITS_REQUEST, "output"); + } + else + { + if (mReseedCounter > BLOCK128_RESEED_MAX) + return -1; + + if (IsTooLarge(output, BLOCK128_MAX_BITS_REQUEST / 8)) + throw new ArgumentException("Number of bits per request limited to " + BLOCK128_MAX_BITS_REQUEST, "output"); + } + + if (predictionResistant || mV == null) + { + mV = mEntropySource.GetEntropy(); + if (mV.Length != mEngine.GetBlockSize()) + throw new InvalidOperationException("Insufficient entropy returned"); + } + + int m = output.Length / mR.Length; + + for (int i = 0; i < m; i++) + { + mEngine.ProcessBlock(mDT, 0, mI, 0); + Process(mR, mI, mV); + Process(mV, mR, mI); + + Array.Copy(mR, 0, output, i * mR.Length, mR.Length); + + Increment(mDT); + } + + int bytesToCopy = (output.Length - m * mR.Length); + + if (bytesToCopy > 0) + { + mEngine.ProcessBlock(mDT, 0, mI, 0); + Process(mR, mI, mV); + Process(mV, mR, mI); + + Array.Copy(mR, 0, output, m * mR.Length, bytesToCopy); + + Increment(mDT); + } + + mReseedCounter++; + + return output.Length; + } + + /** + * Reseed the RNG. + */ + internal void Reseed() + { + mV = mEntropySource.GetEntropy(); + if (mV.Length != mEngine.GetBlockSize()) + throw new InvalidOperationException("Insufficient entropy returned"); + mReseedCounter = 1; + } + + private void Process(byte[] res, byte[] a, byte[] b) + { + for (int i = 0; i != res.Length; i++) + { + res[i] = (byte)(a[i] ^ b[i]); + } + + mEngine.ProcessBlock(res, 0, res, 0); + } + + private void Increment(byte[] val) + { + for (int i = val.Length - 1; i >= 0; i--) + { + if (++val[i] != 0) + break; + } + } + + private static bool IsTooLarge(byte[] bytes, int maxBytes) + { + return bytes != null && bytes.Length > maxBytes; + } + } +} diff --git a/crypto/src/crypto/prng/X931SecureRandom.cs b/crypto/src/crypto/prng/X931SecureRandom.cs new file mode 100644 index 000000000..a87bf1567 --- /dev/null +++ b/crypto/src/crypto/prng/X931SecureRandom.cs @@ -0,0 +1,72 @@ +using System; + +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Prng +{ + public class X931SecureRandom + : SecureRandom + { + private readonly bool mPredictionResistant; + private readonly SecureRandom mRandomSource; + private readonly X931Rng mDrbg; + + internal X931SecureRandom(SecureRandom randomSource, X931Rng drbg, bool predictionResistant) + : base((IRandomGenerator)null) + { + this.mRandomSource = randomSource; + this.mDrbg = drbg; + this.mPredictionResistant = predictionResistant; + } + + public override void SetSeed(byte[] seed) + { + lock (this) + { + if (mRandomSource != null) + { + this.mRandomSource.SetSeed(seed); + } + } + } + + public override void SetSeed(long seed) + { + lock (this) + { + // this will happen when SecureRandom() is created + if (mRandomSource != null) + { + this.mRandomSource.SetSeed(seed); + } + } + } + + public override void NextBytes(byte[] bytes) + { + lock (this) + { + // check if a reseed is required... + if (mDrbg.Generate(bytes, mPredictionResistant) < 0) + { + mDrbg.Reseed(); + mDrbg.Generate(bytes, mPredictionResistant); + } + } + } + + public override void NextBytes(byte[] buf, int off, int len) + { + byte[] bytes = new byte[len]; + NextBytes(bytes); + Array.Copy(bytes, 0, buf, off, len); + } + + public override byte[] GenerateSeed(int numBytes) + { + byte[] bytes = new byte[numBytes]; + NextBytes(bytes); + return bytes; + } + } +} diff --git a/crypto/src/crypto/prng/X931SecureRandomBuilder.cs b/crypto/src/crypto/prng/X931SecureRandomBuilder.cs new file mode 100644 index 000000000..31e94312e --- /dev/null +++ b/crypto/src/crypto/prng/X931SecureRandomBuilder.cs @@ -0,0 +1,87 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Utilities; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Date; + +namespace Org.BouncyCastle.Crypto.Prng +{ + public class X931SecureRandomBuilder + { + private readonly SecureRandom mRandom; // JDK 1.1 complains on final. + + private IEntropySourceProvider mEntropySourceProvider; + private byte[] mDateTimeVector; + + /** + * Basic constructor, creates a builder using an EntropySourceProvider based on the default SecureRandom with + * predictionResistant set to false. + *

    + * Any SecureRandom created from a builder constructed like this will make use of input passed to SecureRandom.setSeed() if + * the default SecureRandom does for its generateSeed() call. + *

    + */ + public X931SecureRandomBuilder() + : this(new SecureRandom(), false) + { + } + + /** + * Construct a builder with an EntropySourceProvider based on the passed in SecureRandom and the passed in value + * for prediction resistance. + *

    + * Any SecureRandom created from a builder constructed like this will make use of input passed to SecureRandom.setSeed() if + * the passed in SecureRandom does for its generateSeed() call. + *

    + * @param entropySource + * @param predictionResistant + */ + public X931SecureRandomBuilder(SecureRandom entropySource, bool predictionResistant) + { + this.mRandom = entropySource; + this.mEntropySourceProvider = new BasicEntropySourceProvider(mRandom, predictionResistant); + } + + /** + * Create a builder which makes creates the SecureRandom objects from a specified entropy source provider. + *

    + * Note: If this constructor is used any calls to setSeed() in the resulting SecureRandom will be ignored. + *

    + * @param entropySourceProvider a provider of EntropySource objects. + */ + public X931SecureRandomBuilder(IEntropySourceProvider entropySourceProvider) + { + this.mRandom = null; + this.mEntropySourceProvider = entropySourceProvider; + } + + public X931SecureRandomBuilder SetDateTimeVector(byte[] dateTimeVector) + { + this.mDateTimeVector = dateTimeVector; + return this; + } + + /** + * Construct a X9.31 secure random generator using the passed in engine and key. If predictionResistant is true the + * generator will be reseeded on each request. + * + * @param engine a block cipher to use as the operator. + * @param key the block cipher key to initialise engine with. + * @param predictionResistant true if engine to be reseeded on each use, false otherwise. + * @return a SecureRandom. + */ + public X931SecureRandom Build(IBlockCipher engine, KeyParameter key, bool predictionResistant) + { + if (mDateTimeVector == null) + { + mDateTimeVector = new byte[engine.GetBlockSize()]; + Pack.UInt64_To_BE((ulong)DateTimeUtilities.CurrentUnixMs(), mDateTimeVector, 0); + } + + engine.Init(true, key); + + return new X931SecureRandom(mRandom, new X931Rng(engine, mDateTimeVector, mEntropySourceProvider.Get(engine.GetBlockSize() * 8)), predictionResistant); + } + } +} diff --git a/crypto/src/crypto/prng/drbg/CtrSP800Drbg.cs b/crypto/src/crypto/prng/drbg/CtrSP800Drbg.cs index d9595d530..2e4fbe4ed 100644 --- a/crypto/src/crypto/prng/drbg/CtrSP800Drbg.cs +++ b/crypto/src/crypto/prng/drbg/CtrSP800Drbg.cs @@ -1,5 +1,6 @@ using System; +using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Utilities; using Org.BouncyCastle.Utilities.Encoders; @@ -8,24 +9,25 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg /** * A SP800-90A CTR DRBG. */ - public class CTRSP800Drbg: SP80090Drbg + public class CtrSP800Drbg + : ISP80090Drbg { - private static readonly long TDEA_RESEED_MAX = 1L << (32 - 1); - private static readonly long AES_RESEED_MAX = 1L << (48 - 1); - private static readonly int TDEA_MAX_BITS_REQUEST = 1 << (13 - 1); - private static readonly int AES_MAX_BITS_REQUEST = 1 << (19 - 1); - - private IEntropySource _entropySource; - private IBlockCipher _engine; - private int _keySizeInBits; - private int _seedLength; - private int _securityStrength; - - // internal state - private byte[] _Key; - private byte[] _V; - private long _reseedCounter = 0; - private bool _isTDEA = false; + private static readonly long TDEA_RESEED_MAX = 1L << (32 - 1); + private static readonly long AES_RESEED_MAX = 1L << (48 - 1); + private static readonly int TDEA_MAX_BITS_REQUEST = 1 << (13 - 1); + private static readonly int AES_MAX_BITS_REQUEST = 1 << (19 - 1); + + private readonly IEntropySource mEntropySource; + private readonly IBlockCipher mEngine; + private readonly int mKeySizeInBits; + private readonly int mSeedLength; + private readonly int mSecurityStrength; + + // internal state + private byte[] mKey; + private byte[] mV; + private long mReseedCounter = 0; + private bool mIsTdea = false; /** * Construct a SP800-90A CTR DRBG. @@ -39,66 +41,58 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg * @param personalizationString personalization string to distinguish this DRBG (may be null). * @param nonce nonce to further distinguish this DRBG (may be null). */ - public CTRSP800Drbg(IBlockCipher engine, int keySizeInBits, int securityStrength, IEntropySource entropySource, byte[] personalizationString, byte[] nonce) + public CtrSP800Drbg(IBlockCipher engine, int keySizeInBits, int securityStrength, IEntropySource entropySource, + byte[] personalizationString, byte[] nonce) { - _entropySource = entropySource; - _engine = engine; - - _keySizeInBits = keySizeInBits; - _securityStrength = securityStrength; - _seedLength = keySizeInBits + engine.getBlockSize() * 8; - _isTDEA = isTDEA(engine); - if (securityStrength > 256) - { throw new ArgumentException("Requested security strength is not supported by the derivation function"); - } - - if (getMaxSecurityStrength(engine, keySizeInBits) < securityStrength) - { + if (GetMaxSecurityStrength(engine, keySizeInBits) < securityStrength) throw new ArgumentException("Requested security strength is not supported by block cipher and key size"); - } - if (entropySource.EntropySize < securityStrength) - { throw new ArgumentException("Not enough entropy for security strength required"); - } - byte[] entropy = getEntropy(); // Get_entropy_input + mEntropySource = entropySource; + mEngine = engine; + + mKeySizeInBits = keySizeInBits; + mSecurityStrength = securityStrength; + mSeedLength = keySizeInBits + engine.GetBlockSize() * 8; + mIsTdea = IsTdea(engine); + + byte[] entropy = GetEntropy(); // Get_entropy_input - CTR_DRBG_Instantiate_algorithm(entropy, nonce, personalizationString); + CTR_DRBG_Instantiate_algorithm(entropy, nonce, personalizationString); } - private void CTR_DRBG_Instantiate_algorithm(byte[] entropy, byte[] nonce, - byte[] personalisationString) + private void CTR_DRBG_Instantiate_algorithm(byte[] entropy, byte[] nonce, byte[] personalisationString) { - byte[] seedMaterial = Arrays.Concatenate(entropy, nonce, personalisationString); - byte[] seed = Block_Cipher_df(seedMaterial, _seedLength); + byte[] seedMaterial = Arrays.ConcatenateAll(entropy, nonce, personalisationString); + byte[] seed = Block_Cipher_df(seedMaterial, mSeedLength); - int outlen = _engine.getBlockSize(); + int outlen = mEngine.GetBlockSize(); - _Key = new byte[(_keySizeInBits + 7) / 8]; - _V = new byte[outlen]; + mKey = new byte[(mKeySizeInBits + 7) / 8]; + mV = new byte[outlen]; - // _Key & _V are modified by this call - CTR_DRBG_Update(seed, _Key, _V); + // mKey & mV are modified by this call + CTR_DRBG_Update(seed, mKey, mV); - _reseedCounter = 1; + mReseedCounter = 1; } - private void CTR_DRBG_Update(byte[] seed, byte[] key, byte[] v) + private void CTR_DRBG_Update(byte[] seed, byte[] key, byte[] v) { byte[] temp = new byte[seed.Length]; - byte[] outputBlock = new byte[_engine.getBlockSize()]; - - int i=0; - int outLen = _engine.getBlockSize(); + byte[] outputBlock = new byte[mEngine.GetBlockSize()]; + + int i = 0; + int outLen = mEngine.GetBlockSize(); - _engine.init(true, new KeyParameter(expandKey(key))); + mEngine.Init(true, new KeyParameter(ExpandKey(key))); while (i*outLen < seed.Length) { - addOneTo(v); - _engine.processBlock(v, 0, outputBlock, 0); + AddOneTo(v); + mEngine.ProcessBlock(v, 0, outputBlock, 0); int bytesToCopy = ((temp.Length - i * outLen) > outLen) ? outLen : (temp.Length - i * outLen); @@ -115,49 +109,48 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg private void CTR_DRBG_Reseed_algorithm(byte[] additionalInput) { - byte[] seedMaterial = Arrays.Concatenate(getEntropy(), additionalInput); + byte[] seedMaterial = Arrays.Concatenate(GetEntropy(), additionalInput); - seedMaterial = Block_Cipher_df(seedMaterial, _seedLength); + seedMaterial = Block_Cipher_df(seedMaterial, mSeedLength); - CTR_DRBG_Update(seedMaterial, _Key, _V); + CTR_DRBG_Update(seedMaterial, mKey, mV); - _reseedCounter = 1; + mReseedCounter = 1; } - private void XOR(byte[] output, byte[] a, byte[] b, int bOff) + private void XOR(byte[] output, byte[] a, byte[] b, int bOff) { - for (int i=0; i< output.Length; i++) + for (int i = 0; i < output.Length; i++) { - output[i] = (byte)(a[i] ^ b[i+bOff]); + output[i] = (byte)(a[i] ^ b[bOff + i]); } } - - private void addOneTo(byte[] longer) + + private void AddOneTo(byte[] longer) { - int carry = 1; - for (int i = 1; i <= longer.Length; i++) // warning - { - int res = (longer[longer.Length - i] & 0xff) + carry; - carry = (res > 0xff) ? 1 : 0; - longer[longer.Length - i] = (byte)res; - } + uint carry = 1; + int i = longer.Length; + while (--i >= 0) + { + carry += longer[i]; + longer[i] = (byte)carry; + carry >>= 8; + } } - private byte[] getEntropy() + private byte[] GetEntropy() { - byte[] entropy = _entropySource.getEntropy(); - if (entropy.Length < (_securityStrength + 7) / 8) - { - throw new IllegalStateException("Insufficient entropy provided by entropy source"); - } + byte[] entropy = mEntropySource.GetEntropy(); + if (entropy.Length < (mSecurityStrength + 7) / 8) + throw new InvalidOperationException("Insufficient entropy provided by entropy source"); return entropy; } // -- Internal state migration --- - - private static final byte[] K_BITS = Hex.decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"); - // 1. If (number_of_bits_to_return > max_number_of_bits), then return an + private static readonly byte[] K_BITS = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"); + + // 1. If (number_of_bits_to_return > max_number_of_bits), then return an // ERROR_FLAG. // 2. L = len (input_string)/8. // 3. N = number_of_bits_to_return/8. @@ -219,7 +212,7 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg // 15. Return SUCCESS and requested_bits. private byte[] Block_Cipher_df(byte[] inputString, int bitLength) { - int outLen = _engine.getBlockSize(); + int outLen = mEngine.GetBlockSize(); int L = inputString.Length; // already in bytes int N = bitLength / 8; // 4 S = L || N || inputstring || 0x80 @@ -232,16 +225,16 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg S[8 + L] = (byte)0x80; // S already padded with zeros - byte[] temp = new byte[_keySizeInBits / 8 + outLen]; + byte[] temp = new byte[mKeySizeInBits / 8 + outLen]; byte[] bccOut = new byte[outLen]; byte[] IV = new byte[outLen]; int i = 0; - byte[] K = new byte[_keySizeInBits / 8]; + byte[] K = new byte[mKeySizeInBits / 8]; Array.Copy(K_BITS, 0, K, 0, K.Length); - while (i*outLen*8 < _keySizeInBits + outLen *8) + while (i*outLen*8 < mKeySizeInBits + outLen *8) { copyIntToByteArray(IV, i, 0); BCC(bccOut, K, IV, S); @@ -261,11 +254,11 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg temp = new byte[bitLength / 2]; i = 0; - _engine.init(true, new KeyParameter(expandKey(K))); + mEngine.Init(true, new KeyParameter(ExpandKey(K))); while (i * outLen < temp.Length) { - _engine.processBlock(X, 0, X, 0); + mEngine.ProcessBlock(X, 0, X, 0); int bytesToCopy = ((temp.Length - i * outLen) > outLen) ? outLen @@ -292,23 +285,23 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg */ private void BCC(byte[] bccOut, byte[] k, byte[] iV, byte[] data) { - int outlen = _engine.getBlockSize(); + int outlen = mEngine.GetBlockSize(); byte[] chainingValue = new byte[outlen]; // initial values = 0 int n = data.Length / outlen; byte[] inputBlock = new byte[outlen]; - _engine.init(true, new KeyParameter(expandKey(k))); + mEngine.Init(true, new KeyParameter(ExpandKey(k))); - _engine.processBlock(iV, 0, chainingValue, 0); + mEngine.ProcessBlock(iV, 0, chainingValue, 0); - for (int i = 0; i < n; i++) + for (int i = 0; i < n; i++) { XOR(inputBlock, chainingValue, data, i*outlen); - _engine.processBlock(inputBlock, 0, chainingValue, 0); + mEngine.ProcessBlock(inputBlock, 0, chainingValue, 0); } - Array.Copy(chainingValue, 0, bccOut, 0, bccOut.Length); + Array.Copy(chainingValue, 0, bccOut, 0, bccOut.Length); } private void copyIntToByteArray(byte[] buf, int value, int offSet) @@ -326,9 +319,7 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg */ public int BlockSize { - get { - return _V.Length * 8; - } + get { return mV.Length * 8; } } /** @@ -342,32 +333,24 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg */ public int Generate(byte[] output, byte[] additionalInput, bool predictionResistant) { - if (_isTDEA) + if (mIsTdea) { - if (_reseedCounter > TDEA_RESEED_MAX) - { + if (mReseedCounter > TDEA_RESEED_MAX) return -1; - } - if (Utils.isTooLarge(output, TDEA_MAX_BITS_REQUEST / 8)) - { - throw new ArgumentException("Number of bits per request limited to " + TDEA_MAX_BITS_REQUEST); - } + if (DrbgUtilities.IsTooLarge(output, TDEA_MAX_BITS_REQUEST / 8)) + throw new ArgumentException("Number of bits per request limited to " + TDEA_MAX_BITS_REQUEST, "output"); } else { - if (_reseedCounter > AES_RESEED_MAX) - { + if (mReseedCounter > AES_RESEED_MAX) return -1; - } - if (Utils.isTooLarge(output, AES_MAX_BITS_REQUEST / 8)) - { - throw new ArgumentException("Number of bits per request limited to " + AES_MAX_BITS_REQUEST); - } + if (DrbgUtilities.IsTooLarge(output, AES_MAX_BITS_REQUEST / 8)) + throw new ArgumentException("Number of bits per request limited to " + AES_MAX_BITS_REQUEST, "output"); } - if (predictionResistant) + if (predictionResistant) { CTR_DRBG_Reseed_algorithm(additionalInput); additionalInput = null; @@ -375,39 +358,39 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg if (additionalInput != null) { - additionalInput = Block_Cipher_df(additionalInput, _seedLength); - CTR_DRBG_Update(additionalInput, _Key, _V); + additionalInput = Block_Cipher_df(additionalInput, mSeedLength); + CTR_DRBG_Update(additionalInput, mKey, mV); } else { - additionalInput = new byte[_seedLength]; + additionalInput = new byte[mSeedLength]; } - byte[] tmp = new byte[_V.Length]; + byte[] tmp = new byte[mV.Length]; - _engine.init(true, new KeyParameter(expandKey(_Key))); + mEngine.Init(true, new KeyParameter(ExpandKey(mKey))); - for (int i = 0; i <= output.Length / tmp.Length; i++) + for (int i = 0; i <= output.Length / tmp.Length; i++) { - int bytesToCopy = ((output.Length - i * tmp.Length) > tmp.Length) - ? tmp.Length - : (output.Length - i * _V.Length); + int bytesToCopy = ((output.Length - i * tmp.Length) > tmp.Length) + ? tmp.Length + : (output.Length - i * mV.Length); - if (bytesToCopy != 0) + if (bytesToCopy != 0) { - addOneTo(_V); + AddOneTo(mV); - _engine.processBlock(_V, 0, tmp, 0); + mEngine.ProcessBlock(mV, 0, tmp, 0); - Array.Copy(tmp, 0, output, i * tmp.Length, bytesToCopy); + Array.Copy(tmp, 0, output, i * tmp.Length, bytesToCopy); } } - CTR_DRBG_Update(additionalInput, _Key, _V); + CTR_DRBG_Update(additionalInput, mKey, mV); - _reseedCounter++; + mReseedCounter++; - return output.Length * 8; + return output.Length * 8; } /** @@ -420,14 +403,14 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg CTR_DRBG_Reseed_algorithm(additionalInput); } - private boolean isTDEA(BlockCipher cipher) + private bool IsTdea(IBlockCipher cipher) { return cipher.AlgorithmName.Equals("DESede") || cipher.AlgorithmName.Equals("TDEA"); } - private int getMaxSecurityStrength(BlockCipher cipher, int keySizeInBits) + private int GetMaxSecurityStrength(IBlockCipher cipher, int keySizeInBits) { - if (isTDEA(cipher) && keySizeInBits == 168) + if (IsTdea(cipher) && keySizeInBits == 168) { return 112; } @@ -436,19 +419,19 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg return keySizeInBits; } - return -1; + return -1; } - byte[] expandKey(byte[] key) + private byte[] ExpandKey(byte[] key) { - if (_isTDEA) + if (mIsTdea) { // expand key to 192 bits. byte[] tmp = new byte[24]; - padKey(key, 0, tmp, 0); - padKey(key, 7, tmp, 8); - padKey(key, 14, tmp, 16); + PadKey(key, 0, tmp, 0); + PadKey(key, 7, tmp, 8); + PadKey(key, 14, tmp, 16); return tmp; } @@ -466,7 +449,7 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg * @param tmp * @param tmpOff */ - private void padKey(byte[] keyMaster, int keyOff, byte[] tmp, int tmpOff) + private void PadKey(byte[] keyMaster, int keyOff, byte[] tmp, int tmpOff) { tmp[tmpOff + 0] = (byte)(keyMaster[keyOff + 0] & 0xfe); tmp[tmpOff + 1] = (byte)((keyMaster[keyOff + 0] << 7) | ((keyMaster[keyOff + 1] & 0xfc) >> 1)); @@ -479,15 +462,15 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg for (int i = tmpOff; i <= tmpOff + 7; i++) { - int b = tmp[i]; - tmp[i] = (byte)((b & 0xfe) | - ((((b >> 1) ^ - (b >> 2) ^ - (b >> 3) ^ - (b >> 4) ^ - (b >> 5) ^ - (b >> 6) ^ - (b >> 7)) ^ 0x01) & 0x01)); + uint b = tmp[i]; + + uint parity = b ^ 1U; + parity ^= (parity >> 4); + parity ^= (parity >> 2); + parity ^= (parity >> 1); + parity &= 1U; + + tmp[i] = (byte)(b ^ parity); } } } diff --git a/crypto/src/crypto/prng/drbg/DrbgUtilities.cs b/crypto/src/crypto/prng/drbg/DrbgUtilities.cs index b5f3b5830..d9a1c439c 100644 --- a/crypto/src/crypto/prng/drbg/DrbgUtilities.cs +++ b/crypto/src/crypto/prng/drbg/DrbgUtilities.cs @@ -5,39 +5,39 @@ using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Crypto.Prng.Drbg { - internal class Utils + internal class DrbgUtilities { private static readonly IDictionary maxSecurityStrengths = Platform.CreateHashtable(); - static Utils() + static DrbgUtilities() { - maxSecurityStrengths.put("SHA-1", 128); + maxSecurityStrengths.Add("SHA-1", 128); - maxSecurityStrengths.put("SHA-224", 192); - maxSecurityStrengths.put("SHA-256", 256); - maxSecurityStrengths.put("SHA-384", 256); - maxSecurityStrengths.put("SHA-512", 256); + maxSecurityStrengths.Add("SHA-224", 192); + maxSecurityStrengths.Add("SHA-256", 256); + maxSecurityStrengths.Add("SHA-384", 256); + maxSecurityStrengths.Add("SHA-512", 256); - maxSecurityStrengths.put("SHA-512/224", 192); - maxSecurityStrengths.put("SHA-512/256", 256); + maxSecurityStrengths.Add("SHA-512/224", 192); + maxSecurityStrengths.Add("SHA-512/256", 256); } - internal static int getMaxSecurityStrength(IDigest d) + internal static int GetMaxSecurityStrength(IDigest d) { return (int)maxSecurityStrengths[d.AlgorithmName]; } - internal static int getMaxSecurityStrength(IMac m) + internal static int GetMaxSecurityStrength(IMac m) { - String name = m.getAlgorithmName(); + string name = m.AlgorithmName; - return (int)maxSecurityStrengths[name.substring(0, name.indexOf("/"))]; + return (int)maxSecurityStrengths[name.Substring(0, name.IndexOf("/"))]; } /** * Used by both Dual EC and Hash. */ - internal static byte[] hash_df(Digest digest, byte[] seedMaterial, int seedLength) + internal static byte[] HashDF(IDigest digest, byte[] seedMaterial, int seedLength) { // 1. temp = the Null string. // 2. . @@ -52,10 +52,10 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg // 6. Return SUCCESS and requested_bits. byte[] temp = new byte[(seedLength + 7) / 8]; - int len = temp.Length / digest.getDigestSize(); + int len = temp.Length / digest.GetDigestSize(); int counter = 1; - byte[] dig = new byte[digest.getDigestSize()]; + byte[] dig = new byte[digest.GetDigestSize()]; for (int i = 0; i <= len; i++) { @@ -82,20 +82,20 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg if (seedLength % 8 != 0) { int shift = 8 - (seedLength % 8); - int carry = 0; + uint carry = 0; - for (int i = 0; i != temp.Length; i++) + for (int i = 0; i != temp.Length; i++) { - uint b = temp[i] & 0xff; + uint b = temp[i]; temp[i] = (byte)((b >> shift) | (carry << (8 - shift))); carry = b; } } - return temp; + return temp; } - internal static boolean isTooLarge(byte[] bytes, int maxBytes) + internal static bool IsTooLarge(byte[] bytes, int maxBytes) { return bytes != null && bytes.Length > maxBytes; } diff --git a/crypto/src/crypto/prng/drbg/HMacSP800Drbg.cs b/crypto/src/crypto/prng/drbg/HMacSP800Drbg.cs index 78a710097..78331705e 100644 --- a/crypto/src/crypto/prng/drbg/HMacSP800Drbg.cs +++ b/crypto/src/crypto/prng/drbg/HMacSP800Drbg.cs @@ -8,19 +8,21 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg /** * A SP800-90A HMAC DRBG. */ - public class HMacSP800Drbg: SP80090Drbg + public class HMacSP800Drbg + : ISP80090Drbg { - private readonly static long RESEED_MAX = 1L << (48 - 1); - private readonly static int MAX_BITS_REQUEST = 1 << (19 - 1); + private readonly static long RESEED_MAX = 1L << (48 - 1); + private readonly static int MAX_BITS_REQUEST = 1 << (19 - 1); - private byte[] _K; - private byte[] _V; - private long _reseedCounter; - private EntropySource _entropySource; - private Mac _hMac; - private int _securityStrength; + private readonly byte[] mK; + private readonly byte[] mV; + private readonly IEntropySource mEntropySource; + private readonly IMac mHMac; + private readonly int mSecurityStrength; - /** + private long mReseedCounter; + + /** * Construct a SP800-90A Hash DRBG. *

    * Minimum entropy requirement is the security strength requested. @@ -33,33 +35,28 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg */ public HMacSP800Drbg(IMac hMac, int securityStrength, IEntropySource entropySource, byte[] personalizationString, byte[] nonce) { - if (securityStrength > Utils.getMaxSecurityStrength(hMac)) - { + if (securityStrength > DrbgUtilities.GetMaxSecurityStrength(hMac)) throw new ArgumentException("Requested security strength is not supported by the derivation function"); - } - if (entropySource.EntropySize < securityStrength) - { throw new ArgumentException("Not enough entropy for security strength required"); - } - _securityStrength = securityStrength; - _entropySource = entropySource; - _hMac = hMac; + mHMac = hMac; + mSecurityStrength = securityStrength; + mEntropySource = entropySource; - byte[] entropy = getEntropy(); - byte[] seedMaterial = Arrays.Concatenate(entropy, nonce, personalizationString); + byte[] entropy = GetEntropy(); + byte[] seedMaterial = Arrays.ConcatenateAll(entropy, nonce, personalizationString); - _K = new byte[hMac.GetMacSize()]; - _V = new byte[_K.Length]; - Arrays.fill(_V, (byte)1); + mK = new byte[hMac.GetMacSize()]; + mV = new byte[mK.Length]; + Arrays.Fill(mV, (byte)1); - hmac_DRBG_Update(seedMaterial); + hmac_DRBG_Update(seedMaterial); - _reseedCounter = 1; + mReseedCounter = 1; } - private void hmac_DRBG_Update(byte[] seedMaterial) + private void hmac_DRBG_Update(byte[] seedMaterial) { hmac_DRBG_Update_Func(seedMaterial, (byte)0x00); if (seedMaterial != null) @@ -70,22 +67,22 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg private void hmac_DRBG_Update_Func(byte[] seedMaterial, byte vValue) { - _hMac.Init(new KeyParameter(_K)); + mHMac.Init(new KeyParameter(mK)); - _hMac.BlockUpdate(_V, 0, _V.Length); - _hMac.Update(vValue); + mHMac.BlockUpdate(mV, 0, mV.Length); + mHMac.Update(vValue); if (seedMaterial != null) { - _hMac.update(seedMaterial, 0, seedMaterial.Length); + mHMac.BlockUpdate(seedMaterial, 0, seedMaterial.Length); } - _hMac.DoFinal(_K, 0); + mHMac.DoFinal(mK, 0); - _hMac.Init(new KeyParameter(_K)); - _hMac.BlockUpdate(_V, 0, _V.Length); + mHMac.Init(new KeyParameter(mK)); + mHMac.BlockUpdate(mV, 0, mV.Length); - _hMac.DoFinal(_V, 0); + mHMac.DoFinal(mV, 0); } /** @@ -95,9 +92,7 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg */ public int BlockSize { - get { - return _V.Length * 8; - } + get { return mV.Length * 8; } } /** @@ -109,23 +104,21 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg * * @return number of bits generated, -1 if a reseed required. */ - public int Generate(byte[] output, byte[] additionalInput, boolean predictionResistant) + public int Generate(byte[] output, byte[] additionalInput, bool predictionResistant) { int numberOfBits = output.Length * 8; - if (numberOfBits > MAX_BITS_REQUEST) - { - throw new IllegalArgumentException("Number of bits per request limited to " + MAX_BITS_REQUEST); - } + if (numberOfBits > MAX_BITS_REQUEST) + throw new ArgumentException("Number of bits per request limited to " + MAX_BITS_REQUEST, "output"); - if (_reseedCounter > RESEED_MAX) + if (mReseedCounter > RESEED_MAX) { return -1; } - if (predictionResistant) + if (predictionResistant) { - reseed(additionalInput); + Reseed(additionalInput); additionalInput = null; } @@ -135,36 +128,36 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg hmac_DRBG_Update(additionalInput); } - // 3. + // 3. byte[] rv = new byte[output.Length]; - int m = output.Length / _V.Length; + int m = output.Length / mV.Length; - _hMac.Init(new KeyParameter(_K)); + mHMac.Init(new KeyParameter(mK)); for (int i = 0; i < m; i++) { - _hMac.BlockUpdate(_V, 0, _V.Length); - _hMac.DoFinal(_V, 0); + mHMac.BlockUpdate(mV, 0, mV.Length); + mHMac.DoFinal(mV, 0); - Array.Copy(_V, 0, rv, i * _V.Length, _V.Length); + Array.Copy(mV, 0, rv, i * mV.Length, mV.Length); } - if (m * _V.Length < rv.Length) + if (m * mV.Length < rv.Length) { - _hMac.BlockUpdate(_V, 0, _V.Length); - _hMac.DoFinal(_V, 0); + mHMac.BlockUpdate(mV, 0, mV.Length); + mHMac.DoFinal(mV, 0); - Array.Copy(_V, 0, rv, m * _V.Length, rv.Length - (m * _V.Length)); + Array.Copy(mV, 0, rv, m * mV.Length, rv.Length - (m * mV.Length)); } - hmac_DRBG_Update(additionalInput); + hmac_DRBG_Update(additionalInput); - _reseedCounter++; + mReseedCounter++; Array.Copy(rv, 0, output, 0, output.Length); - return numberOfBits; + return numberOfBits; } /** @@ -174,22 +167,19 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg */ public void Reseed(byte[] additionalInput) { - byte[] entropy = getEntropy(); + byte[] entropy = GetEntropy(); byte[] seedMaterial = Arrays.Concatenate(entropy, additionalInput); hmac_DRBG_Update(seedMaterial); - _reseedCounter = 1; + mReseedCounter = 1; } - private byte[] getEntropy() + private byte[] GetEntropy() { - byte[] entropy = _entropySource.GetEntropy(); - - if (entropy.Length < (_securityStrength + 7) / 8) - { - throw new IllegalStateException("Insufficient entropy provided by entropy source"); - } + byte[] entropy = mEntropySource.GetEntropy(); + if (entropy.Length < (mSecurityStrength + 7) / 8) + throw new InvalidOperationException("Insufficient entropy provided by entropy source"); return entropy; } } diff --git a/crypto/src/crypto/prng/drbg/HashSP800Drbg.cs b/crypto/src/crypto/prng/drbg/HashSP800Drbg.cs index 868778817..493da5a75 100644 --- a/crypto/src/crypto/prng/drbg/HashSP800Drbg.cs +++ b/crypto/src/crypto/prng/drbg/HashSP800Drbg.cs @@ -8,36 +8,37 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg /** * A SP800-90A Hash DRBG. */ - public class HashSP800Drbg: SP80090Drbg + public class HashSP800Drbg + : ISP80090Drbg { - private readonly static byte[] ONE = { 0x01 }; + private readonly static byte[] ONE = { 0x01 }; - private readonly static long RESEED_MAX = 1L << (48 - 1); - private readonly static int MAX_BITS_REQUEST = 1 << (19 - 1); + private readonly static long RESEED_MAX = 1L << (48 - 1); + private readonly static int MAX_BITS_REQUEST = 1 << (19 - 1); private static readonly IDictionary seedlens = Platform.CreateHashtable(); static HashSP800Drbg() { - seedlens.Add("SHA-1", 440); - seedlens.Add("SHA-224", 440); - seedlens.Add("SHA-256", 440); - seedlens.Add("SHA-512/256", 440); - seedlens.Add("SHA-512/224", 440); - seedlens.Add("SHA-384", 888); - seedlens.Add("SHA-512", 888); - + seedlens.Add("SHA-1", 440); + seedlens.Add("SHA-224", 440); + seedlens.Add("SHA-256", 440); + seedlens.Add("SHA-512/256", 440); + seedlens.Add("SHA-512/224", 440); + seedlens.Add("SHA-384", 888); + seedlens.Add("SHA-512", 888); } - private IDigest _digest; - private byte[] _V; - private byte[] _C; - private long _reseedCounter; - private IEntropySource _entropySource; - private int _securityStrength; - private int _seedLength; + private readonly IDigest mDigest; + private readonly IEntropySource mEntropySource; + private readonly int mSecurityStrength; + private readonly int mSeedLength; - /** + private byte[] mV; + private byte[] mC; + private long mReseedCounter; + + /** * Construct a SP800-90A Hash DRBG. *

    * Minimum entropy requirement is the security strength requested. @@ -50,22 +51,17 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg */ public HashSP800Drbg(IDigest digest, int securityStrength, IEntropySource entropySource, byte[] personalizationString, byte[] nonce) { - if (securityStrength > Utils.getMaxSecurityStrength(digest)) - { + if (securityStrength > DrbgUtilities.GetMaxSecurityStrength(digest)) throw new ArgumentException("Requested security strength is not supported by the derivation function"); - } - if (entropySource.EntropySize < securityStrength) - { throw new ArgumentException("Not enough entropy for security strength required"); - } - _digest = digest; - _entropySource = entropySource; - _securityStrength = securityStrength; - _seedLength = ((Integer)seedlens.get(digest.getAlgorithmName())).intValue(); + mDigest = digest; + mEntropySource = entropySource; + mSecurityStrength = securityStrength; + mSeedLength = (int)seedlens[digest.AlgorithmName]; - // 1. seed_material = entropy_input || nonce || personalization_string. + // 1. seed_material = entropy_input || nonce || personalization_string. // 2. seed = Hash_df (seed_material, seedlen). // 3. V = seed. // 4. C = Hash_df ((0x00 || V), seedlen). Comment: Preceed V with a byte @@ -73,16 +69,16 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg // 5. reseed_counter = 1. // 6. Return V, C, and reseed_counter as the initial_working_state - byte[] entropy = getEntropy(); - byte[] seedMaterial = Arrays.Concatenate(entropy, nonce, personalizationString); - byte[] seed = Utils.hash_df(_digest, seedMaterial, _seedLength); + byte[] entropy = GetEntropy(); + byte[] seedMaterial = Arrays.ConcatenateAll(entropy, nonce, personalizationString); + byte[] seed = DrbgUtilities.HashDF(mDigest, seedMaterial, mSeedLength); - _V = seed; - byte[] subV = new byte[_V.Length + 1]; - Array.Copy(_V, 0, subV, 1, _V.Length); - _C = Utils.hash_df(_digest, subV, _seedLength); + mV = seed; + byte[] subV = new byte[mV.Length + 1]; + Array.Copy(mV, 0, subV, 1, mV.Length); + mC = DrbgUtilities.HashDF(mDigest, subV, mSeedLength); - _reseedCounter = 1; + mReseedCounter = 1; } /** @@ -92,9 +88,7 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg */ public int BlockSize { - get { - return _digest.GetDigestSize () * 8; - } + get { return mDigest.GetDigestSize () * 8; } } /** @@ -121,97 +115,95 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg // 6. reseed_counter = reseed_counter + 1. // 7. Return SUCCESS, returned_bits, and the new values of V, C, and // reseed_counter for the new_working_state. - int numberOfBits = output.Length*8; + int numberOfBits = output.Length * 8; if (numberOfBits > MAX_BITS_REQUEST) - { - throw new ArgumentException("Number of bits per request limited to " + MAX_BITS_REQUEST); - } + throw new ArgumentException("Number of bits per request limited to " + MAX_BITS_REQUEST, "output"); - if (_reseedCounter > RESEED_MAX) - { + if (mReseedCounter > RESEED_MAX) return -1; - } - if (predictionResistant) + if (predictionResistant) { - reseed(additionalInput); + Reseed(additionalInput); additionalInput = null; } // 2. if (additionalInput != null) { - byte[] newInput = new byte[1 + _V.Length + additionalInput.Length]; + byte[] newInput = new byte[1 + mV.Length + additionalInput.Length]; newInput[0] = 0x02; - Array.Copy(_V, 0, newInput, 1, _V.Length); + Array.Copy(mV, 0, newInput, 1, mV.Length); // TODO: inOff / inLength - Array.Copy(additionalInput, 0, newInput, 1 + _V.Length, additionalInput.Length); - byte[] w = hash(newInput); + Array.Copy(additionalInput, 0, newInput, 1 + mV.Length, additionalInput.Length); + byte[] w = Hash(newInput); - addTo(_V, w); + AddTo(mV, w); } - - // 3. - byte[] rv = hashgen(_V, numberOfBits); - - // 4. - byte[] subH = new byte[_V.Length + 1]; - Array.Copy(_V, 0, subH, 1, _V.Length); + + // 3. + byte[] rv = hashgen(mV, numberOfBits); + + // 4. + byte[] subH = new byte[mV.Length + 1]; + Array.Copy(mV, 0, subH, 1, mV.Length); subH[0] = 0x03; - - byte[] H = hash(subH); - - // 5. - addTo(_V, H); - addTo(_V, _C); + + byte[] H = Hash(subH); + + // 5. + AddTo(mV, H); + AddTo(mV, mC); byte[] c = new byte[4]; - c[0] = (byte)(_reseedCounter >> 24); - c[1] = (byte)(_reseedCounter >> 16); - c[2] = (byte)(_reseedCounter >> 8); - c[3] = (byte)_reseedCounter; - - addTo(_V, c); + c[0] = (byte)(mReseedCounter >> 24); + c[1] = (byte)(mReseedCounter >> 16); + c[2] = (byte)(mReseedCounter >> 8); + c[3] = (byte)mReseedCounter; + + AddTo(mV, c); - _reseedCounter++; + mReseedCounter++; Array.Copy(rv, 0, output, 0, output.Length); return numberOfBits; } - private byte[] getEntropy() + private byte[] GetEntropy() { - byte[] entropy = _entropySource.getEntropy(); - if (entropy.Length < (_securityStrength + 7) / 8) - { - throw new IllegalStateException("Insufficient entropy provided by entropy source"); - } + byte[] entropy = mEntropySource.GetEntropy(); + if (entropy.Length < (mSecurityStrength + 7) / 8) + throw new InvalidOperationException("Insufficient entropy provided by entropy source"); return entropy; } // this will always add the shorter length byte array mathematically to the // longer length byte array. // be careful.... - private void addTo(byte[] longer, byte[] shorter) + private void AddTo(byte[] longer, byte[] shorter) { - int carry = 0; - for (int i=1;i <= shorter.Length; i++) // warning - { - int res = (longer[longer.Length-i] & 0xff) + (shorter[shorter.Length-i] & 0xff) + carry; - carry = (res > 0xff) ? 1 : 0; - longer[longer.Length-i] = (byte)res; - } - - for (int i=shorter.Length+1;i <= longer.Length; i++) // warning - { - int res = (longer[longer.Length-i] & 0xff) + carry; - carry = (res > 0xff) ? 1 : 0; - longer[longer.Length-i] = (byte)res; - } + int off = longer.Length - shorter.Length; + + uint carry = 0; + int i = shorter.Length; + while (--i >= 0) + { + carry += (uint)longer[off + i] + (uint)shorter[i]; + longer[off + i] = (byte)carry; + carry >>= 8; + } + + i = off; + while (--i >= 0) + { + carry += longer[i]; + longer[i] = (byte)carry; + carry >>= 8; + } } - /** + /** * Reseed the DRBG. * * @param additionalInput additional input to be added to the DRBG in this step. @@ -231,33 +223,33 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg // 6. Return V, C, and reseed_counter for the new_working_state. // // Comment: Precede with a byte of all zeros. - byte[] entropy = getEntropy(); - byte[] seedMaterial = Arrays.Concatenate(ONE, _V, entropy, additionalInput); - byte[] seed = Utils.hash_df(_digest, seedMaterial, _seedLength); + byte[] entropy = GetEntropy(); + byte[] seedMaterial = Arrays.ConcatenateAll(ONE, mV, entropy, additionalInput); + byte[] seed = DrbgUtilities.HashDF(mDigest, seedMaterial, mSeedLength); - _V = seed; - byte[] subV = new byte[_V.Length + 1]; + mV = seed; + byte[] subV = new byte[mV.Length + 1]; subV[0] = 0x00; - Array.Copy(_V, 0, subV, 1, _V.Length); - _C = Utils.hash_df(_digest, subV, _seedLength); + Array.Copy(mV, 0, subV, 1, mV.Length); + mC = DrbgUtilities.HashDF(mDigest, subV, mSeedLength); - _reseedCounter = 1; - } - - private byte[] hash(byte[] input) - { - byte[] hash = new byte[_digest.GetDigestSize()]; - doHash(input, hash); - return hash; + mReseedCounter = 1; } - private void doHash(byte[] input, byte[] output) - { - _digest.BlockUpdate(input, 0, input.Length); - _digest.DoFinal(output, 0); - } + private byte[] Hash(byte[] input) + { + byte[] hash = new byte[mDigest.GetDigestSize()]; + DoHash(input, hash); + return hash; + } + + private void DoHash(byte[] input, byte[] output) + { + mDigest.BlockUpdate(input, 0, input.Length); + mDigest.DoFinal(output, 0); + } - // 1. m = [requested_number_of_bits / outlen] + // 1. m = [requested_number_of_bits / outlen] // 2. data = V. // 3. W = the Null string. // 4. For i = 1 to m @@ -268,25 +260,25 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg // 5. returned_bits = Leftmost (requested_no_of_bits) bits of W. private byte[] hashgen(byte[] input, int lengthInBits) { - int digestSize = _digest.GetDigestSize(); + int digestSize = mDigest.GetDigestSize(); int m = (lengthInBits / 8) / digestSize; - byte[] data = new byte[input.Length]; + byte[] data = new byte[input.Length]; Array.Copy(input, 0, data, 0, input.Length); byte[] W = new byte[lengthInBits / 8]; - byte[] dig = new byte[_digest.GetDigestSize()]; + byte[] dig = new byte[mDigest.GetDigestSize()]; for (int i = 0; i <= m; i++) { - doHash(data, dig); + DoHash(data, dig); int bytesToCopy = ((W.Length - i * dig.Length) > dig.Length) ? dig.Length : (W.Length - i * dig.Length); Array.Copy(dig, 0, W, i * dig.Length, bytesToCopy); - addTo(data, ONE); + AddTo(data, ONE); } return W; diff --git a/crypto/src/crypto/prng/drbg/ISP80090Drbg.cs b/crypto/src/crypto/prng/drbg/ISP80090Drbg.cs index c39cf365f..0e398209e 100644 --- a/crypto/src/crypto/prng/drbg/ISP80090Drbg.cs +++ b/crypto/src/crypto/prng/drbg/ISP80090Drbg.cs @@ -1,9 +1,11 @@ +using System; + namespace Org.BouncyCastle.Crypto.Prng.Drbg { /** * Interface to SP800-90A deterministic random bit generators. */ - public interface SP80090Drbg + public interface ISP80090Drbg { /** * Return the block size of the DRBG. diff --git a/crypto/src/security/SecureRandom.cs b/crypto/src/security/SecureRandom.cs index 4894a93e6..875709e57 100644 --- a/crypto/src/security/SecureRandom.cs +++ b/crypto/src/security/SecureRandom.cs @@ -164,13 +164,7 @@ namespace Org.BouncyCastle.Security public override int Next() { - for (;;) - { - int i = NextInt() & int.MaxValue; - - if (i != int.MaxValue) - return i; - } + return NextInt() & int.MaxValue; } public override int Next(int maxValue) @@ -184,11 +178,9 @@ namespace Org.BouncyCastle.Security } // Test whether maxValue is a power of 2 - if ((maxValue & -maxValue) == maxValue) + if ((maxValue & (maxValue - 1)) == 0) { - int val = NextInt() & int.MaxValue; - long lr = ((long) maxValue * (long) val) >> 31; - return (int) lr; + return NextInt() & (maxValue - 1); } int bits, result; @@ -244,16 +236,17 @@ namespace Org.BouncyCastle.Security public virtual int NextInt() { - byte[] intBytes = new byte[4]; - NextBytes(intBytes); - - int result = 0; - for (int i = 0; i < 4; i++) - { - result = (result << 8) + (intBytes[i] & 0xff); - } - - return result; + byte[] bytes = new byte[4]; + NextBytes(bytes); + + uint result = bytes[0]; + result <<= 8; + result |= bytes[1]; + result <<= 8; + result |= bytes[2]; + result <<= 8; + result |= bytes[3]; + return (int)result; } public virtual long NextLong() diff --git a/crypto/src/util/Arrays.cs b/crypto/src/util/Arrays.cs index 32c56b8b5..df9b4e7ee 100644 --- a/crypto/src/util/Arrays.cs +++ b/crypto/src/util/Arrays.cs @@ -591,57 +591,33 @@ namespace Org.BouncyCastle.Utilities return rv; } - public static byte[] Concatenate(byte[] a, byte[] b, byte[] c) + public static byte[] ConcatenateAll(params byte[][] vs) { - if (a != null && b != null && c != null) - { - byte[] rv = new byte[a.Length + b.Length + c.Length]; - - Array.Copy(a, 0, rv, 0, a.Length); - Array.Copy(b, 0, rv, a.Length, b.Length); - Array.Copy(c, 0, rv, a.Length + b.Length, c.Length); + byte[][] nonNull = new byte[vs.Length][]; + int count = 0; + int totalLength = 0; - return rv; - } - else if (b == null) - { - return Concatenate(a, c); - } - else + for (int i = 0; i < vs.Length; ++i) + { + byte[] v = vs[i]; + if (v != null) { - return Concatenate(a, b); + nonNull[count++] = v; + totalLength += v.Length; } - } + } - public static byte[] Concatenate(byte[] a, byte[] b, byte[] c, byte[] d) - { - if (a != null && b != null && c != null && d != null) - { - byte[] rv = new byte[a.Length + b.Length + c.Length + d.Length]; + byte[] result = new byte[totalLength]; + int pos = 0; - Array.Copy(a, 0, rv, 0, a.Length); - Array.Copy(b, 0, rv, a.Length, b.Length); - Array.Copy(c, 0, rv, a.Length + b.Length, c.Length); - Array.Copy(d, 0, rv, a.Length + b.Length + c.Length, d.Length); + for (int j = 0; j < count; ++j) + { + byte[] v = nonNull[j]; + Array.Copy(v, 0, result, pos, v.Length); + pos += v.Length; + } - return rv; - } - else if (d == null) - { - return Concatenate(a, b, c); - } - else if (c == null) - { - return Concatenate(a, b, d); - } - else if (b == null) - { - return Concatenate(a, c, d); - } - else - { - return Concatenate(b, c, d); - } + return result; } public static int[] Concatenate(int[] a, int[] b) diff --git a/crypto/test/src/crypto/prng/test/CtrDrbgTest.cs b/crypto/test/src/crypto/prng/test/CtrDrbgTest.cs index e081ec132..44b08f3a6 100644 --- a/crypto/test/src/crypto/prng/test/CtrDrbgTest.cs +++ b/crypto/test/src/crypto/prng/test/CtrDrbgTest.cs @@ -1,10 +1,11 @@ using System; +using NUnit.Framework; + using Org.BouncyCastle.Crypto.Engines; using Org.BouncyCastle.Crypto.Prng.Drbg; using Org.BouncyCastle.Utilities.Test; using Org.BouncyCastle.Utilities.Encoders; -using NUnit.Framework; using Org.BouncyCastle.Utilities; using Org.BouncyCastle.Crypto.Parameters; @@ -14,356 +15,365 @@ namespace Org.BouncyCastle.Crypto.Prng.Test * CTR DRBG Test */ [TestFixture] - public class CtrDrbgTest : SimpleTest + public class CtrDrbgTest + : SimpleTest { - public override String Name { - get { - return "CTRDRBGTest"; - } + public override string Name + { + get { return "CTRDRBGTest"; } } - public static void main(String[] args) + public static void Main(string[] args) { RunTest(new CtrDrbgTest()); } - private DRBGTestVector[] createTestVectorData() + [Test] + public void TestFunction() { - return new DRBGTestVector[] - { - new DRBGTestVector( - new DesEdeEngine(), 168, - new Bit232EntropyProvider().Get(232), - false, - "20212223242526", - 112, - new String[] - { - "ABC88224514D0316EA3D48AEE3C9A2B4", - "D3D3F372E43E7ABDC4FA293743EED076" - } - ), - new DRBGTestVector( - new DesEdeEngine(), 168, - new Bit232EntropyProvider().Get(232), - false, - "20212223242526", - 112, - new String[] - { - "D4564EE072ACA5BD279536E14F94CB12", - "1CCD9AFEF15A9679BA75E35225585DEA" - } - ) - .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C") - .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBC"), - new DRBGTestVector( - new DesEdeEngine(), 168, - new Bit232EntropyProvider().Get(232), - false, - "20212223242526", - 112, - new String[] - { - "760BED7D92B083B10AF31CF0656081EB", - "FD1AC41482384D823CF3FD6F0E6C88B3" - } - ) - .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C"), - new DRBGTestVector( - new DesEdeEngine(), 168, - new Bit232EntropyProvider().Get(232), - false, - "20212223242526", - 112, - new String[] - { - "7A4C1D7ADC8A67FDB50100ED23583A2C", - "43044D311C0E07541CA5C8B0916976B2" - } - ) - .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C") - .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C") - .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBC"), - new DRBGTestVector( - new DesEdeEngine(), 168, - new Bit232EntropyProvider().Get(232), - true, - "20212223242526", - 112, - new String[] - { - "8FB78ABCA75C9F284E974E36141866BC", - "9D9745FF31C42A4488CBB771B13B5D86" - } - ), - new DRBGTestVector( - new DesEdeEngine(), 168, - new Bit232EntropyProvider().Get(232), - true, - "20212223242526", - 112, - new String[] - { - "0E389920A09B485AA4ABD0CA7E60D89C", - "F4478EC6659A0D3577625B0C73A211DD" - } - ) - .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C") - .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBC"), - new DRBGTestVector( - new DesEdeEngine(), 168, - new Bit232EntropyProvider().Get(232), - true, - "20212223242526", - 112, - new String[] - { - "64983055D014550B39DE699E43130B64", - "035FDDA8582A2214EC722C410A8D95D3" - } - ) - .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C"), - new DRBGTestVector( - new DesEdeEngine(), 168, - new Bit232EntropyProvider().Get(232), - true, - "20212223242526", - 112, - new String[] - { - "A29C1A8C42FBC562D7D1DBA7DC541FFE", - "0BDA66B049429061C013E4228C2F44C6" - } - ) - .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C") - .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C") - .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBC"), - new DRBGTestVector( - new AesFastEngine(), 128, - new Bit256EntropyProvider().Get(256), - false, - "2021222324252627", - 128, - new String[] - { - "8CF59C8CF6888B96EB1C1E3E79D82387AF08A9E5FF75E23F1FBCD4559B6B997E", - "69CDEF912C692D61B1DA4C05146B52EB7B8849BD87937835328254EC25A9180E" - } - ), - new DRBGTestVector( - new AesFastEngine(), 128, - new Bit256EntropyProvider().Get(256), - false, - "2021222324252627", - 128, - new String[] - { - "E8C74A4B7BFFB53BEB80E78CA86BB6DF70E2032AEB473E0DD54D2339CEFCE9D0", - "26B3F823B4DBAFC23B141375E10B3AEB7A0B5DEF1C7D760B6F827D01ECD17AC7" - } - ) - .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F") - .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"), - new DRBGTestVector( - new AesFastEngine(), 128, - new Bit256EntropyProvider().Get(256), - false, - "2021222324252627", - 128, - new String[] - { - "18FDEFBDC43D7A36D5D6D862205765D1D701C9F237007030DF1B8E70EE4EEE29", - "9888F1D38BB1CCE31B363AA1BD9B39616876C30DEE1FF0B7BD8C4C441715C833" - } - ) - .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F"), - new DRBGTestVector( - new AesFastEngine(), 128, - new Bit256EntropyProvider().Get(256), - true, - "2021222324252627", - 128, - new String[] - { - "BFF4B85D68C84529F24F69F9ACF1756E29BA648DDEB825C225FA32BA490EF4A9", - "9BD2635137A52AF7D0FCBEFEFB97EA93A0F4C438BD98956C0DACB04F15EE25B3" - } - ), - new DRBGTestVector( - new AesFastEngine(), 128, - new Bit256EntropyProvider().Get(256), - true, - "2021222324252627", - 128, - new String[] - { - "4573AC8BBB33D7CC4DBEF3EEDF6EAE748B536C3A1082CEE4948CDB51C83A7F9C", - "99C628CDD87BD8C2F1FE443AA7F761DA16886436326323354DA6311FFF5BC678" - } - ) - .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F") - .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"), - new DRBGTestVector( - new AesFastEngine(), 128, - new Bit256EntropyProvider().Get(256), - true, - "2021222324252627", - 128, - new String[] - { - "F324104E2FA14F79D8AA60DF06B93B3BC157324958F0A7EE1E193677A70E0250", - "78F4C840134F40DC001BFAD3A90B5EF4DEBDBFAC3CFDF0CD69A89DC4FD34713F" - } - ) - .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F"), - new DRBGTestVector( - new AesFastEngine(), 192, - new Bit320EntropyProvider().Get(320), - false, - "202122232425262728292A2B", - 192, - new String[] - { - "E231244B3235B085C81604424357E85201E3828B5C45568679A5555F867AAC8C", - "DDD0F7BCCADADAA31A67652259CE569A271DD85CF66C3D6A7E9FAED61F38D219" - } - ) - .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F6061626364656667"), - new DRBGTestVector( - new AesFastEngine(), 192, - new Bit320EntropyProvider().Get(320), - true, - "202122232425262728292A2B", - 192, - new String[] - { - "F780D4A2C25CF8EE7407D948EC0B724A4235D8B20E65081392755CA7912AD7C0", - "BA14617F915BA964CB79276BDADC840C14B631BBD1A59097054FA6DFF863B238" - } - ) - .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F6061626364656667"), - new DRBGTestVector( - new AesFastEngine(), 256, - new Bit384EntropyProvider().Get(384), - false, - "202122232425262728292A2B2C2D2E2F", - 256, - new String[] - { - "47111E146562E9AA2FB2A1B095D37A8165AF8FC7CA611D632BE7D4C145C83900", - "98A28E3B1BA363C9DAF0F6887A1CF52B833D3354D77A7C10837DD63DD2E645F8" - } - ) - .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F") - .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F") - .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"), - new DRBGTestVector( - new AesFastEngine(), 256, - new Bit384EntropyProvider().Get(384), - true, - "202122232425262728292A2B2C2D2E2F", - 256, - new String[] - { - "71BB3F9C9CEAF4E6C92A83EB4C7225010EE150AC75E23F5F77AD5073EF24D88A", - "386DEBBBF091BBF0502957B0329938FB836B82E594A2F5FDD5EB28D4E35528F4" - } - ) - .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F") - .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"), - new DRBGTestVector( - new AesFastEngine(), 256, - new Bit384EntropyProvider().Get(384), - true, - "202122232425262728292A2B2C2D2E2F", - 256, - new String[] - { - "1A2E3FEE9056E98D375525FDC2B63B95B47CE51FCF594D804BD5A17F2E01139B", - "601F95384F0D85946301D1EACE8F645A825CE38F1E2565B0C0C439448E9CA8AC" - } - ) - .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F"), - new DRBGTestVector( - new AesFastEngine(), 256, - new Bit384EntropyProvider().Get(384), - true, - "202122232425262728292A2B2C2D2E2F", - 256, - new String[] - { - "EAE6BCE781807E524D26605EA198077932D01EEB445B9AC6C5D99C101D29F46E", - "738E99C95AF59519AAD37FF3D5180986ADEBAB6E95836725097E50A8D1D0BD28" - } - ) - .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F") - .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F") - .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"), - new DRBGTestVector( - new AesFastEngine(), 256, - new Bit384EntropyProvider().Get(384), - true, - "202122232425262728292A2B2C2D2E2F", - 256, - new String[] - { - "eae6bce781807e524d26605ea198077932d01eeb445b9ac6c5d99c101d29f46e30b27377", - "ec51b55b49904c3ff9e13939f1cf27398993e1b3acb2b0be0be8761261428f0aa8ba2657" - } - ) - .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F") - .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F") - .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECF") + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + + private DrbgTestVector[] CreateTestVectorData() + { + return new DrbgTestVector[] + { + new DrbgTestVector( + new DesEdeEngine(), 168, + new Bit232EntropyProvider().Get(232), + false, + "20212223242526", + 112, + new string[] + { + "ABC88224514D0316EA3D48AEE3C9A2B4", + "D3D3F372E43E7ABDC4FA293743EED076" + } + ), + new DrbgTestVector( + new DesEdeEngine(), 168, + new Bit232EntropyProvider().Get(232), + false, + "20212223242526", + 112, + new string[] + { + "D4564EE072ACA5BD279536E14F94CB12", + "1CCD9AFEF15A9679BA75E35225585DEA" + } + ) + .AddAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C") + .AddAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBC"), + new DrbgTestVector( + new DesEdeEngine(), 168, + new Bit232EntropyProvider().Get(232), + false, + "20212223242526", + 112, + new string[] + { + "760BED7D92B083B10AF31CF0656081EB", + "FD1AC41482384D823CF3FD6F0E6C88B3" + } + ) + .SetPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C"), + new DrbgTestVector( + new DesEdeEngine(), 168, + new Bit232EntropyProvider().Get(232), + false, + "20212223242526", + 112, + new string[] + { + "7A4C1D7ADC8A67FDB50100ED23583A2C", + "43044D311C0E07541CA5C8B0916976B2" + } + ) + .SetPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C") + .AddAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C") + .AddAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBC"), + new DrbgTestVector( + new DesEdeEngine(), 168, + new Bit232EntropyProvider().Get(232), + true, + "20212223242526", + 112, + new string[] + { + "8FB78ABCA75C9F284E974E36141866BC", + "9D9745FF31C42A4488CBB771B13B5D86" + } + ), + new DrbgTestVector( + new DesEdeEngine(), 168, + new Bit232EntropyProvider().Get(232), + true, + "20212223242526", + 112, + new string[] + { + "0E389920A09B485AA4ABD0CA7E60D89C", + "F4478EC6659A0D3577625B0C73A211DD" + } + ) + .AddAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C") + .AddAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBC"), + new DrbgTestVector( + new DesEdeEngine(), 168, + new Bit232EntropyProvider().Get(232), + true, + "20212223242526", + 112, + new string[] + { + "64983055D014550B39DE699E43130B64", + "035FDDA8582A2214EC722C410A8D95D3" + } + ) + .SetPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C"), + new DrbgTestVector( + new DesEdeEngine(), 168, + new Bit232EntropyProvider().Get(232), + true, + "20212223242526", + 112, + new string[] + { + "A29C1A8C42FBC562D7D1DBA7DC541FFE", + "0BDA66B049429061C013E4228C2F44C6" + } + ) + .SetPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C") + .AddAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C") + .AddAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBC"), + new DrbgTestVector( + new AesFastEngine(), 128, + new Bit256EntropyProvider().Get(256), + false, + "2021222324252627", + 128, + new string[] + { + "8CF59C8CF6888B96EB1C1E3E79D82387AF08A9E5FF75E23F1FBCD4559B6B997E", + "69CDEF912C692D61B1DA4C05146B52EB7B8849BD87937835328254EC25A9180E" + } + ), + new DrbgTestVector( + new AesFastEngine(), 128, + new Bit256EntropyProvider().Get(256), + false, + "2021222324252627", + 128, + new string[] + { + "E8C74A4B7BFFB53BEB80E78CA86BB6DF70E2032AEB473E0DD54D2339CEFCE9D0", + "26B3F823B4DBAFC23B141375E10B3AEB7A0B5DEF1C7D760B6F827D01ECD17AC7" + } + ) + .AddAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F") + .AddAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"), + new DrbgTestVector( + new AesFastEngine(), 128, + new Bit256EntropyProvider().Get(256), + false, + "2021222324252627", + 128, + new string[] + { + "18FDEFBDC43D7A36D5D6D862205765D1D701C9F237007030DF1B8E70EE4EEE29", + "9888F1D38BB1CCE31B363AA1BD9B39616876C30DEE1FF0B7BD8C4C441715C833" + } + ) + .SetPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F"), + new DrbgTestVector( + new AesFastEngine(), 128, + new Bit256EntropyProvider().Get(256), + true, + "2021222324252627", + 128, + new string[] + { + "BFF4B85D68C84529F24F69F9ACF1756E29BA648DDEB825C225FA32BA490EF4A9", + "9BD2635137A52AF7D0FCBEFEFB97EA93A0F4C438BD98956C0DACB04F15EE25B3" + } + ), + new DrbgTestVector( + new AesFastEngine(), 128, + new Bit256EntropyProvider().Get(256), + true, + "2021222324252627", + 128, + new string[] + { + "4573AC8BBB33D7CC4DBEF3EEDF6EAE748B536C3A1082CEE4948CDB51C83A7F9C", + "99C628CDD87BD8C2F1FE443AA7F761DA16886436326323354DA6311FFF5BC678" + } + ) + .AddAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F") + .AddAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"), + new DrbgTestVector( + new AesFastEngine(), 128, + new Bit256EntropyProvider().Get(256), + true, + "2021222324252627", + 128, + new string[] + { + "F324104E2FA14F79D8AA60DF06B93B3BC157324958F0A7EE1E193677A70E0250", + "78F4C840134F40DC001BFAD3A90B5EF4DEBDBFAC3CFDF0CD69A89DC4FD34713F" + } + ) + .SetPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F"), + new DrbgTestVector( + new AesFastEngine(), 192, + new Bit320EntropyProvider().Get(320), + false, + "202122232425262728292A2B", + 192, + new string[] + { + "E231244B3235B085C81604424357E85201E3828B5C45568679A5555F867AAC8C", + "DDD0F7BCCADADAA31A67652259CE569A271DD85CF66C3D6A7E9FAED61F38D219" + } + ) + .SetPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F6061626364656667"), + new DrbgTestVector( + new AesFastEngine(), 192, + new Bit320EntropyProvider().Get(320), + true, + "202122232425262728292A2B", + 192, + new string[] + { + "F780D4A2C25CF8EE7407D948EC0B724A4235D8B20E65081392755CA7912AD7C0", + "BA14617F915BA964CB79276BDADC840C14B631BBD1A59097054FA6DFF863B238" + } + ) + .SetPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F6061626364656667"), + new DrbgTestVector( + new AesFastEngine(), 256, + new Bit384EntropyProvider().Get(384), + false, + "202122232425262728292A2B2C2D2E2F", + 256, + new string[] + { + "47111E146562E9AA2FB2A1B095D37A8165AF8FC7CA611D632BE7D4C145C83900", + "98A28E3B1BA363C9DAF0F6887A1CF52B833D3354D77A7C10837DD63DD2E645F8" + } + ) + .SetPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F") + .AddAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F") + .AddAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"), + new DrbgTestVector( + new AesFastEngine(), 256, + new Bit384EntropyProvider().Get(384), + true, + "202122232425262728292A2B2C2D2E2F", + 256, + new string[] + { + "71BB3F9C9CEAF4E6C92A83EB4C7225010EE150AC75E23F5F77AD5073EF24D88A", + "386DEBBBF091BBF0502957B0329938FB836B82E594A2F5FDD5EB28D4E35528F4" + } + ) + .AddAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F") + .AddAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"), + new DrbgTestVector( + new AesFastEngine(), 256, + new Bit384EntropyProvider().Get(384), + true, + "202122232425262728292A2B2C2D2E2F", + 256, + new string[] + { + "1A2E3FEE9056E98D375525FDC2B63B95B47CE51FCF594D804BD5A17F2E01139B", + "601F95384F0D85946301D1EACE8F645A825CE38F1E2565B0C0C439448E9CA8AC" + } + ) + .SetPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F"), + new DrbgTestVector( + new AesFastEngine(), 256, + new Bit384EntropyProvider().Get(384), + true, + "202122232425262728292A2B2C2D2E2F", + 256, + new string[] + { + "EAE6BCE781807E524D26605EA198077932D01EEB445B9AC6C5D99C101D29F46E", + "738E99C95AF59519AAD37FF3D5180986ADEBAB6E95836725097E50A8D1D0BD28" + } + ) + .SetPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F") + .AddAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F") + .AddAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"), + new DrbgTestVector( + new AesFastEngine(), 256, + new Bit384EntropyProvider().Get(384), + true, + "202122232425262728292A2B2C2D2E2F", + 256, + new string[] + { + "eae6bce781807e524d26605ea198077932d01eeb445b9ac6c5d99c101d29f46e30b27377", + "ec51b55b49904c3ff9e13939f1cf27398993e1b3acb2b0be0be8761261428f0aa8ba2657" + } + ) + .SetPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F") + .AddAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F") + .AddAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECF") }; } public override void PerformTest() { - DRBGTestVector[] tests = createTestVectorData(); - SP80090Drbg d; - DRBGTestVector tv; + DrbgTestVector[] tests = CreateTestVectorData(); + ISP80090Drbg d; + DrbgTestVector tv; byte[] output; for (int i = 0; i != tests.Length; i++) { tv = tests[i]; - byte[] nonce = tv.nonce(); - byte[] personalisationString = tv.personalizationString(); + byte[] nonce = tv.GetNonce(); + byte[] personalisationString = tv.GetPersonalizationString(); - d = new CtrSP800Drbg(tv.getCipher(), tv.keySizeInBits(), tv.securityStrength(), tv.entropySource(), personalisationString, nonce); + d = new CtrSP800Drbg(tv.Cipher, tv.KeySizeInBits, tv.SecurityStrength, tv.EntropySource, personalisationString, nonce); - output = new byte[tv.expectedValue(0).Length]; + output = new byte[tv.GetExpectedValue(0).Length]; - d.Generate(output, tv.additionalInput(0), tv.predictionResistance()); + d.Generate(output, tv.GetAdditionalInput(0), tv.PredictionResistance); - byte[] expected = tv.expectedValue(0); + byte[] expected = tv.GetExpectedValue(0); if (!AreEqual(expected, output)) { - Fail("Test #" + (i + 1) + ".1 failed, expected " + Hex.ToHexString(tv.expectedValue(0)) + " got " + Hex.ToHexString(output)); + Fail("Test #" + (i + 1) + ".1 failed, expected " + Hex.ToHexString(tv.GetExpectedValue(0)) + " got " + Hex.ToHexString(output)); } - output = new byte[tv.expectedValue(0).Length]; + output = new byte[tv.GetExpectedValue(0).Length]; - d.Generate(output, tv.additionalInput(1), tv.predictionResistance()); + d.Generate(output, tv.GetAdditionalInput(1), tv.PredictionResistance); - expected = tv.expectedValue(1); + expected = tv.GetExpectedValue(1); if (!AreEqual(expected, output)) { - Fail("Test #" + (i + 1) + ".2 failed, expected " + Hex.ToHexString(tv.expectedValue(1)) + " got " + Hex.ToHexString(output)); + Fail("Test #" + (i + 1) + ".2 failed, expected " + Hex.ToHexString(tv.GetExpectedValue(1)) + " got " + Hex.ToHexString(output)); } } // DESede/TDEA key parity test tv = tests[0]; - SP80090Drbg drbg = new CtrSP800Drbg(new KeyParityCipher(tv.getCipher()), tv.keySizeInBits(), tv.securityStrength(), tv.entropySource(), tv.personalizationString(), tv.nonce()); + ISP80090Drbg drbg = new CtrSP800Drbg(new KeyParityCipher(tv.Cipher), tv.KeySizeInBits, tv.SecurityStrength, tv.EntropySource, + tv.GetPersonalizationString(), tv.GetNonce()); - output = new byte[tv.expectedValue(0).Length]; + output = new byte[tv.GetExpectedValue(0).Length]; - drbg.Generate(output, tv.additionalInput(0), tv.predictionResistance()); + drbg.Generate(output, tv.GetAdditionalInput(0), tv.PredictionResistance); // Exception tests try @@ -422,21 +432,21 @@ namespace Org.BouncyCastle.Crypto.Prng.Test internal class Bit232EntropyProvider : TestEntropySourceProvider { internal Bit232EntropyProvider() : base(Hex.Decode( - "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C" + - "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C" + - "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDC"), true) + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C" + + "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C" + + "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDC"), true) { } } internal class Bit256EntropyProvider : TestEntropySourceProvider { internal Bit256EntropyProvider(): base(Hex.Decode( - "0001020304050607" + - "08090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F" + - "8081828384858687" + - "88898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F" + - "C0C1C2C3C4C5C6C7" + - "C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF"), true) + "0001020304050607" + + "08090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F" + + "8081828384858687" + + "88898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F" + + "C0C1C2C3C4C5C6C7" + + "C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF"), true) { } } @@ -489,18 +499,12 @@ namespace Org.BouncyCastle.Crypto.Prng.Test public String AlgorithmName { - get - { - return cipher.AlgorithmName; - } + get { return cipher.AlgorithmName; } } public bool IsPartialBlockOkay { - get - { - return false; - } + get { return false; } } public int GetBlockSize() @@ -518,7 +522,5 @@ namespace Org.BouncyCastle.Crypto.Prng.Test cipher.Reset(); } } - } - } diff --git a/crypto/test/src/crypto/prng/test/DrbgTestVector.cs b/crypto/test/src/crypto/prng/test/DrbgTestVector.cs index a4129b9f8..e0a8eeaf5 100644 --- a/crypto/test/src/crypto/prng/test/DrbgTestVector.cs +++ b/crypto/test/src/crypto/prng/test/DrbgTestVector.cs @@ -1,24 +1,25 @@ -using Org.BouncyCastle.Utilities.Encoders; -using System; -using System.Collections.Generic; -using System.Text; +using System; +using System.Collections; + +using Org.BouncyCastle.Utilities.Encoders; namespace Org.BouncyCastle.Crypto.Prng.Test { - public class DRBGTestVector + public class DrbgTestVector { private IDigest _digest; private IBlockCipher _cipher; private int _keySizeInBits; private IEntropySource _eSource; private bool _pr; - private String _nonce; - private String _personalisation; + private string _nonce; + private string _personalisation; private int _ss; private String[] _ev; - private List _ai = new List(); + private IList _ai = new ArrayList(); - public DRBGTestVector(IDigest digest, IEntropySource eSource, bool predictionResistance, String nonce, int securityStrength, String[] expected) + public DrbgTestVector(IDigest digest, IEntropySource eSource, bool predictionResistance, string nonce, + int securityStrength, string[] expected) { _digest = digest; _eSource = eSource; @@ -29,7 +30,8 @@ namespace Org.BouncyCastle.Crypto.Prng.Test _personalisation = null; } - public DRBGTestVector(IBlockCipher cipher, int keySizeInBits, IEntropySource eSource, bool predictionResistance, String nonce, int securityStrength, String[] expected) + public DrbgTestVector(IBlockCipher cipher, int keySizeInBits, IEntropySource eSource, bool predictionResistance, + string nonce, int securityStrength, string[] expected) { _cipher = cipher; _keySizeInBits = keySizeInBits; @@ -41,89 +43,69 @@ namespace Org.BouncyCastle.Crypto.Prng.Test _personalisation = null; } - public IDigest getDigest() + public IDigest Digest { - return _digest; + get { return _digest; } } - public IBlockCipher getCipher() + public IBlockCipher Cipher { - return _cipher; + get { return _cipher; } } - public int keySizeInBits() + public int KeySizeInBits { - return _keySizeInBits; + get { return _keySizeInBits; } } - public DRBGTestVector addAdditionalInput(String input) + public DrbgTestVector AddAdditionalInput(string input) { _ai.Add(input); - return this; } - public DRBGTestVector setPersonalizationString(String p) + public DrbgTestVector SetPersonalizationString(string p) { _personalisation = p; - return this; } - public IEntropySource entropySource() + public IEntropySource EntropySource { - return _eSource; + get { return _eSource; } } - public bool predictionResistance() + public bool PredictionResistance { - return _pr; + get { return _pr; } } - public byte[] nonce() + public byte[] GetNonce() { - if (_nonce == null) - { - return null; - } - - return Hex.Decode(_nonce); + return _nonce == null ? null : Hex.Decode(_nonce); } - public byte[] personalizationString() + public byte[] GetPersonalizationString() { - if (_personalisation == null) - { - return null; - } - - return Hex.Decode(_personalisation); + return _personalisation == null ? null : Hex.Decode(_personalisation); } - public int securityStrength() + public int SecurityStrength { - return _ss; + get { return _ss; } } - public byte[] expectedValue(int index) + public byte[] GetExpectedValue(int index) { return Hex.Decode(_ev[index]); } - public byte[] additionalInput(int position) + public byte[] GetAdditionalInput(int position) { - int len = _ai.Count; - byte[] rv; - if (position >= len) - { - rv = null; - } - else - { - rv = Hex.Decode((string)(_ai[position])); - } - return rv; - } + if (position >= _ai.Count) + return null; + return Hex.Decode((string)_ai[position]); + } } } diff --git a/crypto/test/src/crypto/prng/test/HMacDrbgTest.cs b/crypto/test/src/crypto/prng/test/HMacDrbgTest.cs index b8d383663..a5ca30836 100644 --- a/crypto/test/src/crypto/prng/test/HMacDrbgTest.cs +++ b/crypto/test/src/crypto/prng/test/HMacDrbgTest.cs @@ -1,12 +1,12 @@ - -using System; +using System; + +using NUnit.Framework; using Org.BouncyCastle.Crypto.Digests; using Org.BouncyCastle.Crypto.Macs; using Org.BouncyCastle.Crypto.Prng.Drbg; using Org.BouncyCastle.Utilities.Test; using Org.BouncyCastle.Utilities.Encoders; -using NUnit.Framework; namespace Org.BouncyCastle.Crypto.Prng.Test { @@ -14,142 +14,141 @@ namespace Org.BouncyCastle.Crypto.Prng.Test * HMAC SP800-90 DRBG */ [TestFixture] - public class HMacDrbgTest : SimpleTest + public class HMacDrbgTest + : SimpleTest { - public override String Name + public override string Name { - get - { - return "HMacDRBG"; - } + get { return "HMacDRBG"; } } - public static void main(String[] args) + public static void Main(string[] args) { RunTest(new HMacDrbgTest()); } [Test] - public void HMacDrbgTestFunction() + public void TestFunction() { string resultText = Perform().ToString(); Assert.AreEqual(Name + ": Okay", resultText); } - private DRBGTestVector[] createTestVectorData() + private DrbgTestVector[] CreateTestVectorData() { - return new DRBGTestVector[] - { - new DRBGTestVector( + return new DrbgTestVector[] + { + new DrbgTestVector( new Sha1Digest(), new SHA1EntropyProvider().Get(440), false, "2021222324", 80, - new String[] - { - "5A7D3B449F481CB38DF79AD2B1FCC01E57F8135E8C0B22CD0630BFB0127FB5408C8EFC17A929896E", - "82cf772ec3e84b00fc74f5df104efbfb2428554e9ce367d03aeade37827fa8e9cb6a08196115d948" - }), - new DRBGTestVector( + new string[] + { + "5A7D3B449F481CB38DF79AD2B1FCC01E57F8135E8C0B22CD0630BFB0127FB5408C8EFC17A929896E", + "82cf772ec3e84b00fc74f5df104efbfb2428554e9ce367d03aeade37827fa8e9cb6a08196115d948" + }), + new DrbgTestVector( new Sha1Digest(), new SHA1EntropyProvider().Get(440), false, "2021222324", 80, - new String[] - { - "B3BD05246CBA12A64735A4E3FDE599BC1BE30F439BD060208EEA7D71F9D123DF47B3CE069D98EDE6", - "B5DADA380E2872DF935BCA55B882C8C9376902AB639765472B71ACEBE2EA8B1B6B49629CB67317E0" - }) - .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F70717273747576"), - new DRBGTestVector( + new string[] + { + "B3BD05246CBA12A64735A4E3FDE599BC1BE30F439BD060208EEA7D71F9D123DF47B3CE069D98EDE6", + "B5DADA380E2872DF935BCA55B882C8C9376902AB639765472B71ACEBE2EA8B1B6B49629CB67317E0" + }) + .SetPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F70717273747576"), + new DrbgTestVector( new Sha1Digest(), new SHA1EntropyProvider().Get(440), false, "2021222324", 80, - new String[] - { - "C7AAAC583C6EF6300714C2CC5D06C148CFFB40449AD0BB26FAC0497B5C57E161E36681BCC930CE80", - "6EBD2B7B5E0A2AD7A24B1BF9A1DBA47D43271719B9C37B7FE81BA94045A14A7CB514B446666EA5A7" - }) - .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F90919293949596") - .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6"), - new DRBGTestVector( + new string[] + { + "C7AAAC583C6EF6300714C2CC5D06C148CFFB40449AD0BB26FAC0497B5C57E161E36681BCC930CE80", + "6EBD2B7B5E0A2AD7A24B1BF9A1DBA47D43271719B9C37B7FE81BA94045A14A7CB514B446666EA5A7" + }) + .AddAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F90919293949596") + .AddAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6"), + new DrbgTestVector( new Sha1Digest(), new SHA1EntropyProvider().Get(440), true, "2021222324", 80, - new String[] - { - "FEC4597F06A3A8CC8529D59557B9E661053809C0BC0EFC282ABD87605CC90CBA9B8633DCB1DAE02E", - "84ADD5E2D2041C01723A4DE4335B13EFDF16B0E51A0AD39BD15E862E644F31E4A2D7D843E57C5968" - }), - new DRBGTestVector( + new string[] + { + "FEC4597F06A3A8CC8529D59557B9E661053809C0BC0EFC282ABD87605CC90CBA9B8633DCB1DAE02E", + "84ADD5E2D2041C01723A4DE4335B13EFDF16B0E51A0AD39BD15E862E644F31E4A2D7D843E57C5968" + }), + new DrbgTestVector( new Sha1Digest(), new SHA1EntropyProvider().Get(440), true, "2021222324", 80, - new String[] - { - "6C37FDD729AA40F80BC6AB08CA7CC649794F6998B57081E4220F22C5C283E2C91B8E305AB869C625", - "CAF57DCFEA393B9236BF691FA456FEA7FDF1DF8361482CA54D5FA723F4C88B4FA504BF03277FA783" - }) - .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F70717273747576"), - new DRBGTestVector( + new string[] + { + "6C37FDD729AA40F80BC6AB08CA7CC649794F6998B57081E4220F22C5C283E2C91B8E305AB869C625", + "CAF57DCFEA393B9236BF691FA456FEA7FDF1DF8361482CA54D5FA723F4C88B4FA504BF03277FA783" + }) + .SetPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F70717273747576"), + new DrbgTestVector( new Sha1Digest(), new SHA1EntropyProvider().Get(440), true, "2021222324", 80, - new String[] - { - "A1BA8FA58BB5013F43F7B6ED52B4539FA16DC77957AEE815B9C07004C7E992EB8C7E591964AFEEA2", - "84264A73A818C95C2F424B37D3CC990B046FB50C2DC64A164211889A010F2471A0912FFEA1BF0195" - }) - .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F90919293949596") - .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6"), - new DRBGTestVector( + new string[] + { + "A1BA8FA58BB5013F43F7B6ED52B4539FA16DC77957AEE815B9C07004C7E992EB8C7E591964AFEEA2", + "84264A73A818C95C2F424B37D3CC990B046FB50C2DC64A164211889A010F2471A0912FFEA1BF0195" + }) + .AddAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F90919293949596") + .AddAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6"), + new DrbgTestVector( new Sha256Digest(), new SHA256EntropyProvider().Get(440), false, "2021222324252627", 128, - new String[] - { - "D67B8C1734F46FA3F763CF57C6F9F4F2" + - "DC1089BD8BC1F6F023950BFC5617635208C8501238AD7A44" + - "00DEFEE46C640B61AF77C2D1A3BFAA90EDE5D207406E5403", - "8FDAEC20F8B421407059E3588920DA7E" + - "DA9DCE3CF8274DFA1C59C108C1D0AA9B0FA38DA5C792037C" + - "4D33CD070CA7CD0C5608DBA8B885654639DE2187B74CB263" - }), - new DRBGTestVector( + new string[] + { + "D67B8C1734F46FA3F763CF57C6F9F4F2" + + "DC1089BD8BC1F6F023950BFC5617635208C8501238AD7A44" + + "00DEFEE46C640B61AF77C2D1A3BFAA90EDE5D207406E5403", + "8FDAEC20F8B421407059E3588920DA7E" + + "DA9DCE3CF8274DFA1C59C108C1D0AA9B0FA38DA5C792037C" + + "4D33CD070CA7CD0C5608DBA8B885654639DE2187B74CB263" + }), + new DrbgTestVector( new Sha256Digest(), new SHA256EntropyProvider().Get(440), true, "2021222324252627", 128, - new String[] - { - "FABD0AE25C69DC2EFDEFB7F20C5A31B5" + - "7AC938AB771AA19BF8F5F1468F665C938C9A1A5DF0628A56" + - "90F15A1AD8A613F31BBD65EEAD5457D5D26947F29FE91AA7", - "6BD925B0E1C232EFD67CCD84F722E927" + - "ECB46AB2B740014777AF14BA0BBF53A45BDBB62B3F7D0B9C" + - "8EEAD057C0EC754EF8B53E60A1F434F05946A8B686AFBC7A" - }), - new DRBGTestVector( + new string[] + { + "FABD0AE25C69DC2EFDEFB7F20C5A31B5" + + "7AC938AB771AA19BF8F5F1468F665C938C9A1A5DF0628A56" + + "90F15A1AD8A613F31BBD65EEAD5457D5D26947F29FE91AA7", + "6BD925B0E1C232EFD67CCD84F722E927" + + "ECB46AB2B740014777AF14BA0BBF53A45BDBB62B3F7D0B9C" + + "8EEAD057C0EC754EF8B53E60A1F434F05946A8B686AFBC7A" + }), + new DrbgTestVector( new Sha384Digest(), new SHA384EntropyProvider().Get(888), false, "202122232425262728292A2B", 192, - new String[]{ + new string[] + { "03AB8BCE4D1DBBB636C5C5B7E1C58499FEB1C619CDD11D35" + "CD6CF6BB8F20EF27B6F5F9054FF900DB9EBF7BF30ED4DCBB" + "BC8D5B51C965EA226FFEE2CA5AB2EFD00754DC32F357BF7A" + @@ -157,20 +156,22 @@ namespace Org.BouncyCastle.Crypto.Prng.Test "B907E77144FD55A54E9BA1A6A0EED0AAC780020C41A15DD8" + "9A6C163830BA1D094E6A17100FF71EE30A96E1EE04D2A966" + "03832A4E404F1966C2B5F4CB61B9927E8D12AC1E1A24CF23" + - "88C14E8EC96C35181EAEE32AAA46330DEAAFE5E7CE783C74"}) - .setPersonalizationString( - "404142434445464748494A4B4C4D4E" + - "4F505152535455565758595A5B5C5D5E5F60616263646566" + - "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" + - "7F808182838485868788898A8B8C8D8E8F90919293949596" + - "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"), - new DRBGTestVector( + "88C14E8EC96C35181EAEE32AAA46330DEAAFE5E7CE783C74" + }) + .SetPersonalizationString( + "404142434445464748494A4B4C4D4E" + + "4F505152535455565758595A5B5C5D5E5F60616263646566" + + "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" + + "7F808182838485868788898A8B8C8D8E8F90919293949596" + + "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"), + new DrbgTestVector( new Sha384Digest(), new SHA384EntropyProvider().Get(888), true, "202122232425262728292A2B", 192, - new String[]{ + new string[] + { "804A3AD720F4FCE8738D0632514FEF16430CB7D63A8DF1A5" + "F02A3CE3BD7ED6A668B69E63E2BB93F096EE753D6194A0F1" + "A32711063653009636337D22167CC4402D019AC216FA574F" + @@ -178,45 +179,49 @@ namespace Org.BouncyCastle.Crypto.Prng.Test "73B8E55C753202176A17B9B9754A9FE6F23B01861FCD4059" + "6AEAA301AF1AEF8AF0EAF22FBF34541EFFAB1431666ACACC" + "759338C7E28672819D53CFEF10A3E19DAFBD53295F1980A9" + - "F491504A2725506784B7AC826D92C838A8668171CAAA86E7"}) - .setPersonalizationString( - "404142434445464748494A4B4C4D4E" + - "4F505152535455565758595A5B5C5D5E5F60616263646566" + - "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" + - "7F808182838485868788898A8B8C8D8E8F90919293949596" + - "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"), - new DRBGTestVector( + "F491504A2725506784B7AC826D92C838A8668171CAAA86E7" + }) + .SetPersonalizationString( + "404142434445464748494A4B4C4D4E" + + "4F505152535455565758595A5B5C5D5E5F60616263646566" + + "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" + + "7F808182838485868788898A8B8C8D8E8F90919293949596" + + "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"), + new DrbgTestVector( new Sha512Digest(), new SHA512EntropyProvider().Get(888), false, "202122232425262728292A2B2C2D2E2F", 256, - new String[]{ + new string[] + { "2A5FF6520C20F66E" + - "D5EA431BD4AEAC58F975EEC9A015137D5C94B73AA09CB8B5" + - "9D611DDEECEB34A52BB999424009EB9EAC5353F92A6699D2" + - "0A02164EEBBC6492941E10426323898465DFD731C7E04730" + - "60A5AA8973841FDF3446FB6E72A58DA8BDA2A57A36F3DD98" + - "6DF85C8A5C6FF31CDE660BF8A841B21DD6AA9D3AC356B87B", + "D5EA431BD4AEAC58F975EEC9A015137D5C94B73AA09CB8B5" + + "9D611DDEECEB34A52BB999424009EB9EAC5353F92A6699D2" + + "0A02164EEBBC6492941E10426323898465DFD731C7E04730" + + "60A5AA8973841FDF3446FB6E72A58DA8BDA2A57A36F3DD98" + + "6DF85C8A5C6FF31CDE660BF8A841B21DD6AA9D3AC356B87B", "0EDC8D7D7CEEC7FE" + - "36333FB30C0A9A4B27AA0BECBF075568B006C1C3693B1C29" + - "0F84769C213F98EB5880909EDF068FDA6BFC43503987BBBD" + - "4FC23AFBE982FE4B4B007910CC4874EEC217405421C8D8A1" + - "BA87EC684D0AF9A6101D9DB787AE82C3A6A25ED478DF1B12" + - "212CEC325466F3AC7C48A56166DD0B119C8673A1A9D54F67"}) - .setPersonalizationString( - "404142434445464748494A4B4C4D4E" + - "4F505152535455565758595A5B5C5D5E5F60616263646566" + - "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" + - "7F808182838485868788898A8B8C8D8E8F90919293949596" + - "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"), - new DRBGTestVector( + "36333FB30C0A9A4B27AA0BECBF075568B006C1C3693B1C29" + + "0F84769C213F98EB5880909EDF068FDA6BFC43503987BBBD" + + "4FC23AFBE982FE4B4B007910CC4874EEC217405421C8D8A1" + + "BA87EC684D0AF9A6101D9DB787AE82C3A6A25ED478DF1B12" + + "212CEC325466F3AC7C48A56166DD0B119C8673A1A9D54F67" + }) + .SetPersonalizationString( + "404142434445464748494A4B4C4D4E" + + "4F505152535455565758595A5B5C5D5E5F60616263646566" + + "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" + + "7F808182838485868788898A8B8C8D8E8F90919293949596" + + "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"), + new DrbgTestVector( new Sha512Digest(), new SHA512EntropyProvider().Get(888), true, "202122232425262728292A2B2C2D2E2F", 256, - new String[]{ + new string[] + { "AAE4DC3C9ECC74D9" + "061DD527117EF3D29E1E52B26853C539D6CA797E8DA3D0BB" + "171D8E30B8B194D8C28F7F6BE3B986B88506DC6A01B294A7" + @@ -228,20 +233,22 @@ namespace Org.BouncyCastle.Crypto.Prng.Test "B9D8E5093ECE7B6BF48638D8F704D134ADDEB7F4E9D5C142" + "CD05683E72B516486AF24AEC15D61E81E270DD4EBED91B62" + "12EB8896A6250D5C8BC3A4A12F7E3068FBDF856F47EB23D3" + - "79F82C1EBCD1585FB260B9C0C42625FBCEE68CAD773CD5B1"}) - .setPersonalizationString( + "79F82C1EBCD1585FB260B9C0C42625FBCEE68CAD773CD5B1" + }) + .SetPersonalizationString( "404142434445464748494A4B4C4D4E" + - "4F505152535455565758595A5B5C5D5E5F60616263646566" + - "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" + - "7F808182838485868788898A8B8C8D8E8F90919293949596" + - "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"), - new DRBGTestVector( + "4F505152535455565758595A5B5C5D5E5F60616263646566" + + "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" + + "7F808182838485868788898A8B8C8D8E8F90919293949596" + + "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"), + new DrbgTestVector( new Sha512Digest(), new SHA512EntropyProvider().Get(888), false, "202122232425262728292A2B2C2D2E2F", 256, - new String[]{ + new string[] + { "7AE31A2DEC31075F" + "E5972660C16D22ECC0D415C5693001BE5A468B590BC1AE2C" + "43F647F8D681AEEA0D87B79B0B4E5D089CA2C9D327534234" + @@ -253,51 +260,55 @@ namespace Org.BouncyCastle.Crypto.Prng.Test "AB823C29F2EBDEC3EDE962F93D920A1DB59C84E1E879C29F" + "5F9995FC3A6A3AF9B587CA7C13EA197D423E81E1D6469942" + "B6E2CA83A97E91F6B298266AC148A1809776C26AF5E239A5" + - "5A2BEB9E752203A694E1F3FE2B3E6A0C9C314421CDB55FBD "}) - .setPersonalizationString( + "5A2BEB9E752203A694E1F3FE2B3E6A0C9C314421CDB55FBD " + }) + .SetPersonalizationString( "404142434445464748494A4B4C4D4E" + "4F505152535455565758595A5B5C5D5E5F60616263646566" + "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" + "7F808182838485868788898A8B8C8D8E8F90919293949596" + "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE") - .addAdditionalInput( + .AddAdditionalInput( "606162636465666768696A6B6C6D6E" + "6F707172737475767778797A7B7C7D7E7F80818283848586" + "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" + "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" + "B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCE") - .addAdditionalInput( + .AddAdditionalInput( "A0A1A2A3A4A5A6A7A8A9AAABACADAE" + "AFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6" + "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" + "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6" + "F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E"), - new DRBGTestVector( + new DrbgTestVector( new Sha512Digest(), new SHA512EntropyProvider().Get(888), true, "202122232425262728292A2B2C2D2E2F", 256, - new String[]{ + new string[] + { "28FD6060C4F35F4D" + - "317AB2060EE32019E0DAA330F3F5650BBCA57CB67EE6AF1C" + - "6F25D1B01F3601EDA85DC2ED29A9B2BA4C85CF491CE7185F" + - "1A2BD9378AE3C655BD1CEC2EE108AE7FC382989F6D4FEA8A" + - "B01499697C2F07945CE02C5ED617D04287FEAF3BA638A4CE" + - "F3BB6B827E40AF16279580FCF1FDAD830930F7FDE341E2AF", + "317AB2060EE32019E0DAA330F3F5650BBCA57CB67EE6AF1C" + + "6F25D1B01F3601EDA85DC2ED29A9B2BA4C85CF491CE7185F" + + "1A2BD9378AE3C655BD1CEC2EE108AE7FC382989F6D4FEA8A" + + "B01499697C2F07945CE02C5ED617D04287FEAF3BA638A4CE" + + "F3BB6B827E40AF16279580FCF1FDAD830930F7FDE341E2AF", "C0B1601AFE39338B" + - "58DC2BE7C256AEBE3C21C5A939BEEC7E97B3528AC420F0C6" + - "341847187666E0FF578A8EB0A37809F877365A28DF2FA0F0" + - "6354A6F02496747369375B9A9D6B756FDC4A8FB308E08256" + - "9D79A85BB960F747256626389A3B45B0ABE7ECBC39D5CD7B" + - "2C18DF2E5FDE8C9B8D43474C54B6F9839468445929B438C7"}), - new DRBGTestVector( + "58DC2BE7C256AEBE3C21C5A939BEEC7E97B3528AC420F0C6" + + "341847187666E0FF578A8EB0A37809F877365A28DF2FA0F0" + + "6354A6F02496747369375B9A9D6B756FDC4A8FB308E08256" + + "9D79A85BB960F747256626389A3B45B0ABE7ECBC39D5CD7B" + + "2C18DF2E5FDE8C9B8D43474C54B6F9839468445929B438C7" + }), + new DrbgTestVector( new Sha512Digest(), new SHA512EntropyProvider().Get(888), true, "202122232425262728292A2B2C2D2E2F", 256, - new String[]{ + new string[] + { "72691D2103FB567C" + "CD30370715B36666F63430087B1C688281CA0974DB456BDB" + "A7EB5C48CFF62EA05F9508F3B530CE995A272B11EC079C13" + @@ -309,26 +320,28 @@ namespace Org.BouncyCastle.Crypto.Prng.Test "2F12BEB71D801C0942E7C0864B3DB67A9356DB203490D881" + "24FE86BCE38AC2269B4FDA6ABAA884039DF80A0336A24D79" + "1EB3067C8F5F0CF0F18DD73B66A7B316FB19E02835CC6293" + - "65FCD1D3BE640178ED9093B91B36E1D68135F2785BFF505C"}) - .addAdditionalInput( + "65FCD1D3BE640178ED9093B91B36E1D68135F2785BFF505C" + }) + .AddAdditionalInput( "606162636465666768696A6B6C6D6E" + "6F707172737475767778797A7B7C7D7E7F80818283848586" + "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" + "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" + "B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCE") - .addAdditionalInput( + .AddAdditionalInput( "A0A1A2A3A4A5A6A7A8A9AAABACADAE" + "AFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6" + "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" + "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6" + "F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E"), - new DRBGTestVector( + new DrbgTestVector( new Sha512Digest(), new SHA512EntropyProvider().Get(888), true, "202122232425262728292A2B2C2D2E2F", 256, - new String[]{ + new string[] + { "AAE4DC3C9ECC74D9" + "061DD527117EF3D29E1E52B26853C539D6CA797E8DA3D0BB" + "171D8E30B8B194D8C28F7F6BE3B986B88506DC6A01B294A7" + @@ -340,20 +353,22 @@ namespace Org.BouncyCastle.Crypto.Prng.Test "B9D8E5093ECE7B6BF48638D8F704D134ADDEB7F4E9D5C142" + "CD05683E72B516486AF24AEC15D61E81E270DD4EBED91B62" + "12EB8896A6250D5C8BC3A4A12F7E3068FBDF856F47EB23D3" + - "79F82C1EBCD1585FB260B9C0C42625FBCEE68CAD773CD5B1"}) - .setPersonalizationString( + "79F82C1EBCD1585FB260B9C0C42625FBCEE68CAD773CD5B1" + }) + .SetPersonalizationString( "404142434445464748494A4B4C4D4E" + - "4F505152535455565758595A5B5C5D5E5F60616263646566" + - "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" + - "7F808182838485868788898A8B8C8D8E8F90919293949596" + - "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"), - new DRBGTestVector( + "4F505152535455565758595A5B5C5D5E5F60616263646566" + + "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" + + "7F808182838485868788898A8B8C8D8E8F90919293949596" + + "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"), + new DrbgTestVector( new Sha512Digest(), new SHA512EntropyProvider().Get(888), true, "202122232425262728292A2B2C2D2E2F", 256, - new String[]{ + new string[] + { "B8E827652175E6E0" + "6E513C7BE94B5810C14ED94AD903647940CAEB7EE014C848" + "8DCBBE6D4D6616D06656A3DC707CDAC4F02EE6D8408C065F" + @@ -365,61 +380,62 @@ namespace Org.BouncyCastle.Crypto.Prng.Test "BD1B5C196C57CF759BB9871BE0C163A57315EA96F615136D" + "064572F09F26D659D24211F9610FFCDFFDA8CE23FFA96735" + "7595182660877766035EED800B05364CE324A75EB63FD9B3" + - "EED956D147480B1D0A42DF8AA990BB628666F6F61D60CBE2"}) - .setPersonalizationString( + "EED956D147480B1D0A42DF8AA990BB628666F6F61D60CBE2" + }) + .SetPersonalizationString( "404142434445464748494A4B4C4D4E" + - "4F505152535455565758595A5B5C5D5E5F60616263646566" + - "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" + - "7F808182838485868788898A8B8C8D8E8F90919293949596" + - "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE") - .addAdditionalInput( + "4F505152535455565758595A5B5C5D5E5F60616263646566" + + "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" + + "7F808182838485868788898A8B8C8D8E8F90919293949596" + + "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE") + .AddAdditionalInput( "606162636465666768696A6B6C6D6E" + - "6F707172737475767778797A7B7C7D7E7F80818283848586" + - "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" + - "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" + - "B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCE") - .addAdditionalInput( + "6F707172737475767778797A7B7C7D7E7F80818283848586" + + "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" + + "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" + + "B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCE") + .AddAdditionalInput( "A0A1A2A3A4A5A6A7A8A9AAABACADAE" + "AFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6" + "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" + "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6" + "F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E") - }; + }; } public override void PerformTest() { - DRBGTestVector[] tests = createTestVectorData(); - SP80090Drbg d; + DrbgTestVector[] tests = CreateTestVectorData(); + ISP80090Drbg d; for (int i = 0; i != tests.Length; i++) { - DRBGTestVector tv = tests[i]; + DrbgTestVector tv = tests[i]; - byte[] nonce = tv.nonce(); - byte[] personalisationString = tv.personalizationString(); + byte[] nonce = tv.GetNonce(); + byte[] personalisationString = tv.GetPersonalizationString(); - d = new HMacSP800Drbg(new HMac(tv.getDigest()), tv.securityStrength(), tv.entropySource(), personalisationString, nonce); + d = new HMacSP800Drbg(new HMac(tv.Digest), tv.SecurityStrength, tv.EntropySource, personalisationString, nonce); - byte[] output = new byte[tv.expectedValue(0).Length]; + byte[] output = new byte[tv.GetExpectedValue(0).Length]; - d.Generate(output, tv.additionalInput(0), tv.predictionResistance()); + d.Generate(output, tv.GetAdditionalInput(0), tv.PredictionResistance); - byte[] expected = tv.expectedValue(0); + byte[] expected = tv.GetExpectedValue(0); if (!AreEqual(expected, output)) { - Fail("Test #" + (i + 1) + ".1 failed, expected " + Hex.ToHexString(tv.expectedValue(0)) + " got " + Hex.ToHexString(output)); + Fail("Test #" + (i + 1) + ".1 failed, expected " + Hex.ToHexString(tv.GetExpectedValue(0)) + " got " + Hex.ToHexString(output)); } - output = new byte[tv.expectedValue(0).Length]; + output = new byte[tv.GetExpectedValue(0).Length]; - d.Generate(output, tv.additionalInput(1), tv.predictionResistance()); + d.Generate(output, tv.GetAdditionalInput(1), tv.PredictionResistance); - expected = tv.expectedValue(1); + expected = tv.GetExpectedValue(1); if (!AreEqual(expected, output)) { - Fail("Test #" + (i + 1) + ".2 failed, expected " + Hex.ToHexString(tv.expectedValue(1)) + " got " + Hex.ToHexString(output)); + Fail("Test #" + (i + 1) + ".2 failed, expected " + Hex.ToHexString(tv.GetExpectedValue(1)) + " got " + Hex.ToHexString(output)); } } @@ -441,11 +457,10 @@ namespace Org.BouncyCastle.Crypto.Prng.Test private class SHA1EntropyProvider : TestEntropySourceProvider { - internal SHA1EntropyProvider() : base( - Hex.Decode( - "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F30313233343536" - + "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" - + "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6"), true) + internal SHA1EntropyProvider() : base(Hex.Decode( + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F30313233343536" + + "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" + + "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6"), true) { } } @@ -453,15 +468,15 @@ namespace Org.BouncyCastle.Crypto.Prng.Test internal class SHA256EntropyProvider : TestEntropySourceProvider { internal SHA256EntropyProvider() : base(Hex.Decode( - "00010203040506" + - "0708090A0B0C0D0E0F101112131415161718191A1B1C1D1E" + - "1F202122232425262728292A2B2C2D2E2F30313233343536" + - "80818283848586" + - "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" + - "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" + - "C0C1C2C3C4C5C6" + - "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" + - "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6"), true) + "00010203040506" + + "0708090A0B0C0D0E0F101112131415161718191A1B1C1D1E" + + "1F202122232425262728292A2B2C2D2E2F30313233343536" + + "80818283848586" + + "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" + + "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" + + "C0C1C2C3C4C5C6" + + "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" + + "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6"), true) { } } @@ -469,43 +484,41 @@ namespace Org.BouncyCastle.Crypto.Prng.Test internal class SHA384EntropyProvider : TestEntropySourceProvider { internal SHA384EntropyProvider() : base(Hex.Decode( - "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223242526" - + "2728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F50515253545556" - + "5758595A5B5C5D5E5F606162636465666768696A6B6C6D6E" + - "808182838485868788898A8B8C8D8E" + - "8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6" + - "A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBE" + - "BFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6" + - "D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEE" + - "C0C1C2C3C4C5C6C7C8C9CACBCCCDCE" + - "CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6" + - "E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFE" + - "FF000102030405060708090A0B0C0D0E0F10111213141516" + - "1718191A1B1C1D1E1F202122232425262728292A2B2C2D2E"), true) + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223242526" + + "2728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F50515253545556" + + "5758595A5B5C5D5E5F606162636465666768696A6B6C6D6E" + + "808182838485868788898A8B8C8D8E" + + "8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6" + + "A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBE" + + "BFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6" + + "D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEE" + + "C0C1C2C3C4C5C6C7C8C9CACBCCCDCE" + + "CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6" + + "E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFE" + + "FF000102030405060708090A0B0C0D0E0F10111213141516" + + "1718191A1B1C1D1E1F202122232425262728292A2B2C2D2E"), true) { } } internal class SHA512EntropyProvider : TestEntropySourceProvider { - internal SHA512EntropyProvider() : - base(Hex.Decode( - "000102030405060708090A0B0C0D0E" + - "0F101112131415161718191A1B1C1D1E1F20212223242526" + - "2728292A2B2C2D2E2F303132333435363738393A3B3C3D3E" + - "3F404142434445464748494A4B4C4D4E4F50515253545556" + - "5758595A5B5C5D5E5F606162636465666768696A6B6C6D6E" + - "808182838485868788898A8B8C8D8E" + - "8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6" + - "A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBE" + - "BFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6" + - "D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEE" + - "C0C1C2C3C4C5C6C7C8C9CACBCCCDCE" + - "CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6" + - "E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFE" + - "FF000102030405060708090A0B0C0D0E0F10111213141516" + - "1718191A1B1C1D1E1F202122232425262728292A2B2C2D2E"), true) - { - } + internal SHA512EntropyProvider() : base(Hex.Decode( + "000102030405060708090A0B0C0D0E" + + "0F101112131415161718191A1B1C1D1E1F20212223242526" + + "2728292A2B2C2D2E2F303132333435363738393A3B3C3D3E" + + "3F404142434445464748494A4B4C4D4E4F50515253545556" + + "5758595A5B5C5D5E5F606162636465666768696A6B6C6D6E" + + "808182838485868788898A8B8C8D8E" + + "8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6" + + "A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBE" + + "BFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6" + + "D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEE" + + "C0C1C2C3C4C5C6C7C8C9CACBCCCDCE" + + "CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6" + + "E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFE" + + "FF000102030405060708090A0B0C0D0E0F10111213141516" + + "1718191A1B1C1D1E1F202122232425262728292A2B2C2D2E"), true) + { } } } } diff --git a/crypto/test/src/crypto/prng/test/HashDrbgTest.cs b/crypto/test/src/crypto/prng/test/HashDrbgTest.cs index d9776e0d6..892ca74da 100644 --- a/crypto/test/src/crypto/prng/test/HashDrbgTest.cs +++ b/crypto/test/src/crypto/prng/test/HashDrbgTest.cs @@ -1,10 +1,11 @@ using System; +using NUnit.Framework; + using Org.BouncyCastle.Crypto.Digests; using Org.BouncyCastle.Crypto.Prng.Drbg; using Org.BouncyCastle.Utilities.Test; using Org.BouncyCastle.Utilities.Encoders; -using NUnit.Framework; namespace Org.BouncyCastle.Crypto.Prng.Test { @@ -12,365 +13,371 @@ namespace Org.BouncyCastle.Crypto.Prng.Test * DRBG Test */ [TestFixture] - public class HashDrbgTest: SimpleTest + public class HashDrbgTest + : SimpleTest { - public override String Name - { - get - { - return "HashDRBG"; - } + public override string Name + { + get { return "HashDRBG"; } } - public static void main(String[] args) - { + public static void Main(string[] args) + { RunTest(new HashDrbgTest()); } - private DRBGTestVector[] createTestVectorData() - { - return new DRBGTestVector[] - { - new DRBGTestVector( - new Sha1Digest(), - new SHA1EntropyProvider().Get(440), - false, - "2021222324", - 80, - new String[] - { - "9F7CFF1ECA23E750F66326969F11800F12088BA68E441D15D888B3FE12BF66FE057494F4546DE2F1", - "B77AA5C0CD55BBCEED7574AF223AFD988C7EEC8EFF4A94E5E89D26A04F58FA79F5E0D3702D7A9A6A" - } - ), - new DRBGTestVector( + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + + private DrbgTestVector[] CreateTestVectorData() + { + return new DrbgTestVector[] + { + new DrbgTestVector( + new Sha1Digest(), + new SHA1EntropyProvider().Get(440), + false, + "2021222324", + 80, + new string[] + { + "9F7CFF1ECA23E750F66326969F11800F12088BA68E441D15D888B3FE12BF66FE057494F4546DE2F1", + "B77AA5C0CD55BBCEED7574AF223AFD988C7EEC8EFF4A94E5E89D26A04F58FA79F5E0D3702D7A9A6A" + } + ), + new DrbgTestVector( new Sha1Digest(), new SHA1EntropyProvider().Get(440), false, "2021222324", 80, - new String[] - { - "AB438BD3B01A0AF85CFEE29F7D7B71621C4908B909124D430E7B406FB1086EA994C582E0D656D989", - "29D9098F987E7005314A0F51B3DD2B8122F4AED706735DE6AD5DDBF223177C1E5F3AEBC52FAB90B9" - }) - .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F70717273747576"), - new DRBGTestVector( + new string[] + { + "AB438BD3B01A0AF85CFEE29F7D7B71621C4908B909124D430E7B406FB1086EA994C582E0D656D989", + "29D9098F987E7005314A0F51B3DD2B8122F4AED706735DE6AD5DDBF223177C1E5F3AEBC52FAB90B9" + }) + .SetPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F70717273747576"), + new DrbgTestVector( new Sha1Digest(), new SHA1EntropyProvider().Get(440), false, "2021222324", 80, - new String[] - { - "E76B4EDD5C865BC8AFD809A59B69B429AC7F4352A579BCF3F75E56249A3491F87C3CA6848B0FAB25", - "6577B6B4F87A93240B199FE51A3B335313683103DECE171E3256FB7E803586CA4E45DD242EB01F70" - }) - .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F90919293949596") - .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6"), - new DRBGTestVector( + new string[] + { + "E76B4EDD5C865BC8AFD809A59B69B429AC7F4352A579BCF3F75E56249A3491F87C3CA6848B0FAB25", + "6577B6B4F87A93240B199FE51A3B335313683103DECE171E3256FB7E803586CA4E45DD242EB01F70" + }) + .AddAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F90919293949596") + .AddAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6"), + new DrbgTestVector( new Sha1Digest(), new SHA1EntropyProvider().Get(440), true, "2021222324", 80, - new String[] - { - "56EF4913373994D5539F4D7D17AFE7448CDF5E72416CC6A71A340059FA0D5AE526B23250C46C0944", - "575B37A2739814F966C63B60A2C4F149CA9ACC84FC4B25493289B085C67B2E30F5F0B99A2C349E2A" - }), - new DRBGTestVector( + new string[] + { + "56EF4913373994D5539F4D7D17AFE7448CDF5E72416CC6A71A340059FA0D5AE526B23250C46C0944", + "575B37A2739814F966C63B60A2C4F149CA9ACC84FC4B25493289B085C67B2E30F5F0B99A2C349E2A" + }), + new DrbgTestVector( new Sha1Digest(), new SHA1EntropyProvider().Get(440), true, "2021222324", 80, - new String[] - { - "532CA1165DCFF21C55592687639884AF4BC4B057DF8F41DE653AB44E2ADEC7C9303E75ABE277EDBF", - "73C2C67C696D686D0C4DBCEB5C2AF7DDF6F020B6874FAE4390F102117ECAAFF54418529A367005A0" - }) - .setPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F70717273747576"), - new DRBGTestVector( + new string[] + { + "532CA1165DCFF21C55592687639884AF4BC4B057DF8F41DE653AB44E2ADEC7C9303E75ABE277EDBF", + "73C2C67C696D686D0C4DBCEB5C2AF7DDF6F020B6874FAE4390F102117ECAAFF54418529A367005A0" + }) + .SetPersonalizationString("404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F70717273747576"), + new DrbgTestVector( new Sha1Digest(), new SHA1EntropyProvider().Get(440), true, "2021222324", 80, - new String[] - { - "183C242A1430E46C4ED70B4DBE1BF9AB0AB8721CDCA2A2D1820AD6F6C956858543B2AA191D8D1287", - "F196F9BD021C745CBD5AC7BFCE48EAAF0D0E7C091FBF436940E63A198EE770D9A4F0718669AF2BC9" - }) - .addAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F90919293949596") - .addAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6"), - new DRBGTestVector( + new string[] + { + "183C242A1430E46C4ED70B4DBE1BF9AB0AB8721CDCA2A2D1820AD6F6C956858543B2AA191D8D1287", + "F196F9BD021C745CBD5AC7BFCE48EAAF0D0E7C091FBF436940E63A198EE770D9A4F0718669AF2BC9" + }) + .AddAdditionalInput("606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F90919293949596") + .AddAdditionalInput("A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6"), + new DrbgTestVector( new Sha256Digest(), new SHA256EntropyProvider().Get(440), false, "2021222324252627", 128, - new String[] - { - "77E05A0E7DC78AB5D8934D5E93E82C06" + - "A07C04CEE6C9C53045EEB485872777CF3B3E35C474F976B8" + - "94BF301A86FA651F463970E89D4A0534B2ECAD29EC044E7E", - "5FF4BA493C40CFFF3B01E472C575668C" + - "CE3880B9290B05BFEDE5EC96ED5E9B2898508B09BC800EEE" + - "099A3C90602ABD4B1D4F343D497C6055C87BB956D53BF351" - } + new string[] + { + "77E05A0E7DC78AB5D8934D5E93E82C06" + + "A07C04CEE6C9C53045EEB485872777CF3B3E35C474F976B8" + + "94BF301A86FA651F463970E89D4A0534B2ECAD29EC044E7E", + "5FF4BA493C40CFFF3B01E472C575668C" + + "CE3880B9290B05BFEDE5EC96ED5E9B2898508B09BC800EEE" + + "099A3C90602ABD4B1D4F343D497C6055C87BB956D53BF351" + } ), - new DRBGTestVector( + new DrbgTestVector( new Sha256Digest(), new SHA256EntropyProvider().Get(440), true, "2021222324252627", 128, - new String[] - { - "92275523C70E567BCF9B35EC50B933F8" + - "12616DF586B7F72EE1BC7735A5C2654373CBBC72316DFF84" + - "20A33BF02B97AC8D1952583F270ACD7005CC027F4CF1187E", - "681A46B2AA8694A0FE4DEEA720927A84" + - "EAAA985E59C19F8BE0984D8CBEF8C69B754167641946E040" + - "EE2043E1CCB29DCF063C0A50830E428E6DCA262ECD77C542" - }), - new DRBGTestVector( - new Sha384Digest(), - new SHA384EntropyProvider().Get(888), - false, - "202122232425262728292A2B", - 192, - new String[] - { - "04FF23AD15E78790ADD36B438BBC097C7A11747CC2CCEEDE" + - "2C978B23B3DC63B732C953061D7764990ABFEFC47A581B92" + - "1BC0428C4F12212460E406A0F0651E7F0CB9A90ABFDB07B5" + - "25565C74F0AA085082F6CF213AAFAD0C0646895078F1E1FE", - "4F35B85F95DEE3E873054905CFD02341653E18F529930CBE" + - "14D909F37FEAF2C790D22FAE7516B4590BE35D53E2FE1A35" + - "AFE4B6607CB358589C3B4D094A1D81FE0717F1DF5BDDEB3E" + - "114F130BB781E66C22B5B770E8AE115FF39F8ADAF66DEEDF" - } - ), - new DRBGTestVector( - new Sha384Digest(), - new SHA384EntropyProvider().Get(888), - true, - "202122232425262728292A2B", - 192, - new String[] - { - "97993B78F7C31C0E876DC92EB7D6C408E09D608AD6B99D0E" + - "A2229B05A578C426334FCC8A1C7E676ED2D89A5B4CDF5B3F" + - "4ADF11936BF14F4E10909DBA9C24F4FDFFDE72351DA8E2CC" + - "3B135A395373899E5F1A5955B880CA9B9E9DD4C9CA7FA4D4", - "F5983946320E36C64EF283CA1F65D197CF81624EC6778E77" + - "0E78949D84EF21A45CDD62D1DB76920D4C2836FC6AE5299F" + - "AF1357D9701FAD10FBD88D1E2832239436D76EB271BDC3CA" + - "04425EC88BC0E89A4D5C37FFCE7C6C3ABDE9C413AE6D3FEA" - } - ), - new DRBGTestVector( - new Sha512Digest(), - new SHA512EntropyProvider().Get(888), - false, - "202122232425262728292A2B2C2D2E2F", - 256, - new String[] - { - "DA126CF95C6BF97E" + - "2F731F2137A907ACC70FD7AC9EBACD1C6E31C74029B052E3" + - "AABC48F3B00993F2B2381F7650A55322A968C86E05DE88E6" + - "367F6EF89A601DB4342E9086C7AC13B5E56C32E9E668040B" + - "73847893C5BFD38A1CF44F348B4EEE4CD68ADB7E7B8C837F" + - "19BC4F902761F7CFF24AB1D704FD11C4E929D8553753B55D", - "400B977CE8A2BB6A" + - "84C6FD1CF901459685ABF5408CFF4588CEDF52E2D2DC300A" + - "A9B4FAED8CD0161C2172B1FD269253195883D6EBF21020F2" + - "C20E5F2C81AE60C8595B834A229B1F5B726C1125717E6207" + - "8886EF38E61E32707AD5F8116C6393DFB6E7C7AE0E8E92BB" + - "D7E0C3D04BBA02F5169F2F569A58158915FEE4C9D28D45DB" - } - ) - .setPersonalizationString( - "404142434445464748494A4B4C4D4E" + - "4F505152535455565758595A5B5C5D5E5F60616263646566" + - "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" + - "7F808182838485868788898A8B8C8D8E8F90919293949596" + - "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE") - .addAdditionalInput( - "606162636465666768696A6B6C6D6E" + - "6F707172737475767778797A7B7C7D7E7F80818283848586" + - "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" + - "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" + - "B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCE") - .addAdditionalInput( - "A0A1A2A3A4A5A6A7A8A9AAABACADAE" + - "AFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6" + - "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" + - "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6" + - "F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E"), - new DRBGTestVector( - new Sha512Digest(), - new SHA512EntropyProvider().Get(888), - true, - "202122232425262728292A2B2C2D2E2F", - 256, - new String[] - { - "F93CA6855590A77F" + - "07354097E90E026648B6115DF008FFEDBD9D9811F54E8286" + - "EF00FDD6BA1E58DF2535E3FBDD9A9BA3754A97F36EE83322" + - "1582060A1F37FCE4EE8826636B28EAD589593F4CA8B64738" + - "8F24EB3F0A34796968D21BDEE6F81FD5DF93536F935937B8" + - "025EC8CBF57DDB0C61F2E41463CC1516D657DA2829C6BF90", - "4817618F48C60FB1" + - "CE5BFBDA0CAF4591882A31F6EE3FE0F78779992A06EC60F3" + - "7FB9A8D6108C231F0A927754B0599FA4FA27A4E25E065EF0" + - "3085B892979DC0E7A1080883CAEBFDFD3665A8F2D061C521" + - "F7D6E3DA2AF8B97B6B43B6EC831AF515070A83BBB9AC95ED" + - "4EF49B756A2377A5F0833D847E27A88DDB0C2CE4AD782E7B " - } - ), - new DRBGTestVector( - new Sha512Digest(), - new SHA512EntropyProvider().Get(888), - true, - "202122232425262728292A2B2C2D2E2F", - 256, - new String[] - { - "0455DD4AD7DBACB2" + - "410BE58DF7248D765A4547ABAEE1743B0BCAD37EBD06DA7C" + - "F7CE5E2216E525327E9E2005EBEF2CE53BD733B18128627D" + - "3FD6153089373AF2606A1584646A0EA488BFEF45228699A0" + - "89CEA8AEC44502D86D9591F3552C688B7F7B45FCB0C3C2B9" + - "43C1CD8A6FC63DF4D81C3DA543C9CF2843855EA84E4F959C", - "C047D46D7F614E4E" + - "4A7952C79A451F8F7ACA379967E2977C401C626A2ED70D74" + - "A63660579A354115BC8C8C8CC3AEA3050686A0CFCDB6FA9C" + - "F78D4C2165BAF851C6F9B1CD16A2E14C15C6DAAC56C16E75" + - "FC84A14D58B41622E88B0F1B1995587FD8BAA999CBA98025" + - "4C8AB9A9691DF7B84D88B639A9A3106DEABEB63748B99C09" - } - ) - .addAdditionalInput( + new string[] + { + "92275523C70E567BCF9B35EC50B933F8" + + "12616DF586B7F72EE1BC7735A5C2654373CBBC72316DFF84" + + "20A33BF02B97AC8D1952583F270ACD7005CC027F4CF1187E", + "681A46B2AA8694A0FE4DEEA720927A84" + + "EAAA985E59C19F8BE0984D8CBEF8C69B754167641946E040" + + "EE2043E1CCB29DCF063C0A50830E428E6DCA262ECD77C542" + }), + new DrbgTestVector( + new Sha384Digest(), + new SHA384EntropyProvider().Get(888), + false, + "202122232425262728292A2B", + 192, + new string[] + { + "04FF23AD15E78790ADD36B438BBC097C7A11747CC2CCEEDE" + + "2C978B23B3DC63B732C953061D7764990ABFEFC47A581B92" + + "1BC0428C4F12212460E406A0F0651E7F0CB9A90ABFDB07B5" + + "25565C74F0AA085082F6CF213AAFAD0C0646895078F1E1FE", + "4F35B85F95DEE3E873054905CFD02341653E18F529930CBE" + + "14D909F37FEAF2C790D22FAE7516B4590BE35D53E2FE1A35" + + "AFE4B6607CB358589C3B4D094A1D81FE0717F1DF5BDDEB3E" + + "114F130BB781E66C22B5B770E8AE115FF39F8ADAF66DEEDF" + } + ), + new DrbgTestVector( + new Sha384Digest(), + new SHA384EntropyProvider().Get(888), + true, + "202122232425262728292A2B", + 192, + new string[] + { + "97993B78F7C31C0E876DC92EB7D6C408E09D608AD6B99D0E" + + "A2229B05A578C426334FCC8A1C7E676ED2D89A5B4CDF5B3F" + + "4ADF11936BF14F4E10909DBA9C24F4FDFFDE72351DA8E2CC" + + "3B135A395373899E5F1A5955B880CA9B9E9DD4C9CA7FA4D4", + "F5983946320E36C64EF283CA1F65D197CF81624EC6778E77" + + "0E78949D84EF21A45CDD62D1DB76920D4C2836FC6AE5299F" + + "AF1357D9701FAD10FBD88D1E2832239436D76EB271BDC3CA" + + "04425EC88BC0E89A4D5C37FFCE7C6C3ABDE9C413AE6D3FEA" + } + ), + new DrbgTestVector( + new Sha512Digest(), + new SHA512EntropyProvider().Get(888), + false, + "202122232425262728292A2B2C2D2E2F", + 256, + new string[] + { + "DA126CF95C6BF97E" + + "2F731F2137A907ACC70FD7AC9EBACD1C6E31C74029B052E3" + + "AABC48F3B00993F2B2381F7650A55322A968C86E05DE88E6" + + "367F6EF89A601DB4342E9086C7AC13B5E56C32E9E668040B" + + "73847893C5BFD38A1CF44F348B4EEE4CD68ADB7E7B8C837F" + + "19BC4F902761F7CFF24AB1D704FD11C4E929D8553753B55D", + "400B977CE8A2BB6A" + + "84C6FD1CF901459685ABF5408CFF4588CEDF52E2D2DC300A" + + "A9B4FAED8CD0161C2172B1FD269253195883D6EBF21020F2" + + "C20E5F2C81AE60C8595B834A229B1F5B726C1125717E6207" + + "8886EF38E61E32707AD5F8116C6393DFB6E7C7AE0E8E92BB" + + "D7E0C3D04BBA02F5169F2F569A58158915FEE4C9D28D45DB" + } + ) + .SetPersonalizationString( + "404142434445464748494A4B4C4D4E" + + "4F505152535455565758595A5B5C5D5E5F60616263646566" + + "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" + + "7F808182838485868788898A8B8C8D8E8F90919293949596" + + "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE") + .AddAdditionalInput( "606162636465666768696A6B6C6D6E" + "6F707172737475767778797A7B7C7D7E7F80818283848586" + "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" + "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" + "B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCE") - .addAdditionalInput( + .AddAdditionalInput( "A0A1A2A3A4A5A6A7A8A9AAABACADAE" + "AFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6" + "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" + "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6" + "F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E"), - new DRBGTestVector( - new Sha512Digest(), - new SHA512EntropyProvider().Get(888), - true, - "202122232425262728292A2B2C2D2E2F", - 256, - new String[] - { - "22EB93A67911DA73" + - "85D9180C78127DE1A04FF713114C07C9C615F7CC5EF72744" + - "A2DDCD7C3CB85E65DED8EF5F240FBDCBEBBDE2BAAC8ECF7D" + - "CBC8AC333E54607AD41DC495D83DF72A05EF55B127C1441C" + - "9A0EFFDA2C7954DB6C2D04342EB812E5E0B11D6C395F41ED" + - "A2702ECE5BA479E2DFA18F953097492636C12FE30CE5C968", - "E66698CFBF1B3F2E" + - "919C03036E584EAA81CF1C6666240AF05F70637043733954" + - "D8A1E5A66A04C53C6900FDC145D4A3A80A31F5868ACE9AC9" + - "4E14E2051F624A05EEA1F8B684AA5410BCE315E76EA07C71" + - "5D6F34731320FF0DCF78D795E6EFA2DF92B98BE636CDFBA2" + - "9008DD392112AEC202F2E481CB9D83F987FEA69CD1B368BB" - } - ) - .setPersonalizationString( - "404142434445464748494A4B4C4D4E" + - "4F505152535455565758595A5B5C5D5E5F60616263646566" + - "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" + - "7F808182838485868788898A8B8C8D8E8F90919293949596" + - "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"), - new DRBGTestVector( - new Sha512Digest(), - new SHA512EntropyProvider().Get(888), - true, - "202122232425262728292A2B2C2D2E2F", - 256, - new String[] - { - "7596A76372308BD5" + - "A5613439934678B35521A94D81ABFE63A21ACF61ABB88B61" + - "E86A12C37F308F2BBBE32BE4B38D03AE808386494D70EF52" + - "E9E1365DD18B7784CAB826F31D47579E4D57F69D8BF3152B" + - "95741946CEBE58571DF58ED39980D9AF44E69F01E8989759" + - "8E40171101A0E3302838E0AD9E849C01988993CF9F6E5263", - "DBE5EE36FCD85301" + - "303E1C3617C1AC5E23C08885D0BEFAAD0C85A0D89F85B9F1" + - "6ECE3D88A24EB96504F2F13EFA7049621782F5DE2C416A0D" + - "294CCFE53545C4E309C48E1E285A2B829A574B72B3C2FBE1" + - "34D01E3706B486F2401B9820E17298A342666918E15B8462" + - "87F8C5AF2D96B20FAF3D0BB392E15F4A06CDB0DECD1B6AD7" - } - ) - .setPersonalizationString( - "404142434445464748494A4B4C4D4E" + - "4F505152535455565758595A5B5C5D5E5F60616263646566" + - "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" + - "7F808182838485868788898A8B8C8D8E8F90919293949596" + - "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE") - .addAdditionalInput( - "606162636465666768696A6B6C6D6E" + - "6F707172737475767778797A7B7C7D7E7F80818283848586" + - "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" + - "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" + - "B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCE") - .addAdditionalInput( - "A0A1A2A3A4A5A6A7A8A9AAABACADAE" + - "AFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6" + - "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" + - "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6" + - "F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E") + new DrbgTestVector( + new Sha512Digest(), + new SHA512EntropyProvider().Get(888), + true, + "202122232425262728292A2B2C2D2E2F", + 256, + new string[] + { + "F93CA6855590A77F" + + "07354097E90E026648B6115DF008FFEDBD9D9811F54E8286" + + "EF00FDD6BA1E58DF2535E3FBDD9A9BA3754A97F36EE83322" + + "1582060A1F37FCE4EE8826636B28EAD589593F4CA8B64738" + + "8F24EB3F0A34796968D21BDEE6F81FD5DF93536F935937B8" + + "025EC8CBF57DDB0C61F2E41463CC1516D657DA2829C6BF90", + "4817618F48C60FB1" + + "CE5BFBDA0CAF4591882A31F6EE3FE0F78779992A06EC60F3" + + "7FB9A8D6108C231F0A927754B0599FA4FA27A4E25E065EF0" + + "3085B892979DC0E7A1080883CAEBFDFD3665A8F2D061C521" + + "F7D6E3DA2AF8B97B6B43B6EC831AF515070A83BBB9AC95ED" + + "4EF49B756A2377A5F0833D847E27A88DDB0C2CE4AD782E7B " + } + ), + new DrbgTestVector( + new Sha512Digest(), + new SHA512EntropyProvider().Get(888), + true, + "202122232425262728292A2B2C2D2E2F", + 256, + new string[] + { + "0455DD4AD7DBACB2" + + "410BE58DF7248D765A4547ABAEE1743B0BCAD37EBD06DA7C" + + "F7CE5E2216E525327E9E2005EBEF2CE53BD733B18128627D" + + "3FD6153089373AF2606A1584646A0EA488BFEF45228699A0" + + "89CEA8AEC44502D86D9591F3552C688B7F7B45FCB0C3C2B9" + + "43C1CD8A6FC63DF4D81C3DA543C9CF2843855EA84E4F959C", + "C047D46D7F614E4E" + + "4A7952C79A451F8F7ACA379967E2977C401C626A2ED70D74" + + "A63660579A354115BC8C8C8CC3AEA3050686A0CFCDB6FA9C" + + "F78D4C2165BAF851C6F9B1CD16A2E14C15C6DAAC56C16E75" + + "FC84A14D58B41622E88B0F1B1995587FD8BAA999CBA98025" + + "4C8AB9A9691DF7B84D88B639A9A3106DEABEB63748B99C09" + } + ) + .AddAdditionalInput( + "606162636465666768696A6B6C6D6E" + + "6F707172737475767778797A7B7C7D7E7F80818283848586" + + "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" + + "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" + + "B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCE") + .AddAdditionalInput( + "A0A1A2A3A4A5A6A7A8A9AAABACADAE" + + "AFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6" + + "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" + + "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6" + + "F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E"), + new DrbgTestVector( + new Sha512Digest(), + new SHA512EntropyProvider().Get(888), + true, + "202122232425262728292A2B2C2D2E2F", + 256, + new string[] + { + "22EB93A67911DA73" + + "85D9180C78127DE1A04FF713114C07C9C615F7CC5EF72744" + + "A2DDCD7C3CB85E65DED8EF5F240FBDCBEBBDE2BAAC8ECF7D" + + "CBC8AC333E54607AD41DC495D83DF72A05EF55B127C1441C" + + "9A0EFFDA2C7954DB6C2D04342EB812E5E0B11D6C395F41ED" + + "A2702ECE5BA479E2DFA18F953097492636C12FE30CE5C968", + "E66698CFBF1B3F2E" + + "919C03036E584EAA81CF1C6666240AF05F70637043733954" + + "D8A1E5A66A04C53C6900FDC145D4A3A80A31F5868ACE9AC9" + + "4E14E2051F624A05EEA1F8B684AA5410BCE315E76EA07C71" + + "5D6F34731320FF0DCF78D795E6EFA2DF92B98BE636CDFBA2" + + "9008DD392112AEC202F2E481CB9D83F987FEA69CD1B368BB" + } + ) + .SetPersonalizationString( + "404142434445464748494A4B4C4D4E" + + "4F505152535455565758595A5B5C5D5E5F60616263646566" + + "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" + + "7F808182838485868788898A8B8C8D8E8F90919293949596" + + "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE"), + new DrbgTestVector( + new Sha512Digest(), + new SHA512EntropyProvider().Get(888), + true, + "202122232425262728292A2B2C2D2E2F", + 256, + new string[] + { + "7596A76372308BD5" + + "A5613439934678B35521A94D81ABFE63A21ACF61ABB88B61" + + "E86A12C37F308F2BBBE32BE4B38D03AE808386494D70EF52" + + "E9E1365DD18B7784CAB826F31D47579E4D57F69D8BF3152B" + + "95741946CEBE58571DF58ED39980D9AF44E69F01E8989759" + + "8E40171101A0E3302838E0AD9E849C01988993CF9F6E5263", + "DBE5EE36FCD85301" + + "303E1C3617C1AC5E23C08885D0BEFAAD0C85A0D89F85B9F1" + + "6ECE3D88A24EB96504F2F13EFA7049621782F5DE2C416A0D" + + "294CCFE53545C4E309C48E1E285A2B829A574B72B3C2FBE1" + + "34D01E3706B486F2401B9820E17298A342666918E15B8462" + + "87F8C5AF2D96B20FAF3D0BB392E15F4A06CDB0DECD1B6AD7" + } + ) + .SetPersonalizationString( + "404142434445464748494A4B4C4D4E" + + "4F505152535455565758595A5B5C5D5E5F60616263646566" + + "6768696A6B6C6D6E6F707172737475767778797A7B7C7D7E" + + "7F808182838485868788898A8B8C8D8E8F90919293949596" + + "9798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAE") + .AddAdditionalInput( + "606162636465666768696A6B6C6D6E" + + "6F707172737475767778797A7B7C7D7E7F80818283848586" + + "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" + + "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" + + "B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCE") + .AddAdditionalInput( + "A0A1A2A3A4A5A6A7A8A9AAABACADAE" + + "AFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6" + + "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" + + "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6" + + "F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E") }; } public override void PerformTest() { - DRBGTestVector[] tests = createTestVectorData(); - SP80090Drbg d; + DrbgTestVector[] tests = CreateTestVectorData(); + ISP80090Drbg d; for (int i = 0; i != tests.Length; i++) { - DRBGTestVector tv = tests[i]; + DrbgTestVector tv = tests[i]; - byte[] nonce = tv.nonce(); - byte[] personalisationString = tv.personalizationString(); + byte[] nonce = tv.GetNonce(); + byte[] personalisationString = tv.GetPersonalizationString(); - d = new HashSP800Drbg(tv.getDigest(), tv.securityStrength(), tv.entropySource(), personalisationString, nonce); + d = new HashSP800Drbg(tv.Digest, tv.SecurityStrength, tv.EntropySource, personalisationString, nonce); - byte[] output = new byte[tv.expectedValue(0).Length]; + byte[] output = new byte[tv.GetExpectedValue(0).Length]; - d.Generate(output, tv.additionalInput(0), tv.predictionResistance()); + d.Generate(output, tv.GetAdditionalInput(0), tv.PredictionResistance); - byte[] expected = tv.expectedValue(0); + byte[] expected = tv.GetExpectedValue(0); if (!AreEqual(expected, output)) { - Fail("Test #" + (i + 1) + ".1 failed, expected " + Hex.ToHexString(tv.expectedValue(0)) + " got " + Hex.ToHexString(output)); + Fail("Test #" + (i + 1) + ".1 failed, expected " + Hex.ToHexString(tv.GetExpectedValue(0)) + " got " + Hex.ToHexString(output)); } - output = new byte[tv.expectedValue(0).Length]; + output = new byte[tv.GetExpectedValue(0).Length]; - d.Generate(output, tv.additionalInput(1), tv.predictionResistance()); + d.Generate(output, tv.GetAdditionalInput(1), tv.PredictionResistance); - expected = tv.expectedValue(1); + expected = tv.GetExpectedValue(1); if (!AreEqual(expected, output)) { - Fail("Test #" + (i + 1) + ".2 failed, expected " + Hex.ToHexString(tv.expectedValue(1)) + " got " + Hex.ToHexString(output)); + Fail("Test #" + (i + 1) + ".2 failed, expected " + Hex.ToHexString(tv.GetExpectedValue(1)) + " got " + Hex.ToHexString(output)); } } @@ -403,69 +410,68 @@ namespace Org.BouncyCastle.Crypto.Prng.Test } } - internal class SHA1EntropyProvider: TestEntropySourceProvider - { - internal SHA1EntropyProvider(): base( - Hex.Decode( - "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F30313233343536" - + "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" - + "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6"), true) - {} - } + internal class SHA1EntropyProvider : TestEntropySourceProvider + { + internal SHA1EntropyProvider() : base(Hex.Decode( + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F30313233343536" + + "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" + + "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6"), true) + {} + } - internal class SHA256EntropyProvider: TestEntropySourceProvider - { - internal SHA256EntropyProvider(): base(Hex.Decode( + internal class SHA256EntropyProvider : TestEntropySourceProvider + { + internal SHA256EntropyProvider() : base(Hex.Decode( "00010203040506" + - "0708090A0B0C0D0E0F101112131415161718191A1B1C1D1E" + - "1F202122232425262728292A2B2C2D2E2F30313233343536" + - "80818283848586" + - "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" + - "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" + - "C0C1C2C3C4C5C6" + - "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" + - "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6"), true) - { } - } + "0708090A0B0C0D0E0F101112131415161718191A1B1C1D1E" + + "1F202122232425262728292A2B2C2D2E2F30313233343536" + + "80818283848586" + + "8788898A8B8C8D8E8F909192939495969798999A9B9C9D9E" + + "9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6" + + "C0C1C2C3C4C5C6" + + "C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE" + + "DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6"), true) + { } + } - internal class SHA384EntropyProvider: TestEntropySourceProvider - { - internal SHA384EntropyProvider(): base(Hex.Decode( - "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223242526" - + "2728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F50515253545556" - + "5758595A5B5C5D5E5F606162636465666768696A6B6C6D6E" + - "808182838485868788898A8B8C8D8E" + - "8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6" + - "A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBE" + - "BFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6" + - "D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEE" + - "C0C1C2C3C4C5C6C7C8C9CACBCCCDCE" + - "CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6" + - "E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFE" + - "FF000102030405060708090A0B0C0D0E0F10111213141516" + - "1718191A1B1C1D1E1F202122232425262728292A2B2C2D2E"), true) - {} - } + internal class SHA384EntropyProvider : TestEntropySourceProvider + { + internal SHA384EntropyProvider() : base(Hex.Decode( + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223242526" + + "2728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F50515253545556" + + "5758595A5B5C5D5E5F606162636465666768696A6B6C6D6E" + + "808182838485868788898A8B8C8D8E" + + "8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6" + + "A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBE" + + "BFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6" + + "D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEE" + + "C0C1C2C3C4C5C6C7C8C9CACBCCCDCE" + + "CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6" + + "E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFE" + + "FF000102030405060708090A0B0C0D0E0F10111213141516" + + "1718191A1B1C1D1E1F202122232425262728292A2B2C2D2E"), true) + {} + } - internal class SHA512EntropyProvider: TestEntropySourceProvider - { - internal SHA512EntropyProvider(): base(Hex.Decode( + internal class SHA512EntropyProvider : TestEntropySourceProvider + { + internal SHA512EntropyProvider() : base(Hex.Decode( "000102030405060708090A0B0C0D0E" + - "0F101112131415161718191A1B1C1D1E1F20212223242526" + - "2728292A2B2C2D2E2F303132333435363738393A3B3C3D3E" + - "3F404142434445464748494A4B4C4D4E4F50515253545556" + - "5758595A5B5C5D5E5F606162636465666768696A6B6C6D6E" + - "808182838485868788898A8B8C8D8E" + - "8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6" + - "A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBE" + - "BFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6" + - "D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEE" + - "C0C1C2C3C4C5C6C7C8C9CACBCCCDCE" + - "CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6" + - "E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFE" + - "FF000102030405060708090A0B0C0D0E0F10111213141516" + - "1718191A1B1C1D1E1F202122232425262728292A2B2C2D2E"), true) - { } + "0F101112131415161718191A1B1C1D1E1F20212223242526" + + "2728292A2B2C2D2E2F303132333435363738393A3B3C3D3E" + + "3F404142434445464748494A4B4C4D4E4F50515253545556" + + "5758595A5B5C5D5E5F606162636465666768696A6B6C6D6E" + + "808182838485868788898A8B8C8D8E" + + "8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6" + + "A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBE" + + "BFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6" + + "D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEE" + + "C0C1C2C3C4C5C6C7C8C9CACBCCCDCE" + + "CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6" + + "E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFE" + + "FF000102030405060708090A0B0C0D0E0F10111213141516" + + "1718191A1B1C1D1E1F202122232425262728292A2B2C2D2E"), true) + { } + } } } -} diff --git a/crypto/test/src/crypto/prng/test/TestEntropySourceProvider.cs b/crypto/test/src/crypto/prng/test/TestEntropySourceProvider.cs index a37bcd844..647799630 100644 --- a/crypto/test/src/crypto/prng/test/TestEntropySourceProvider.cs +++ b/crypto/test/src/crypto/prng/test/TestEntropySourceProvider.cs @@ -2,7 +2,8 @@ namespace Org.BouncyCastle.Crypto.Prng.Test { - public class TestEntropySourceProvider: IEntropySourceProvider + public class TestEntropySourceProvider + : IEntropySourceProvider { private readonly byte[] data; private readonly bool isPredictionResistant; @@ -18,7 +19,8 @@ namespace Org.BouncyCastle.Crypto.Prng.Test return new EntropySource(bitsRequired, data, isPredictionResistant); } - internal class EntropySource: IEntropySource + internal class EntropySource + : IEntropySource { private readonly int bitsRequired; private readonly byte[] data; @@ -35,30 +37,21 @@ namespace Org.BouncyCastle.Crypto.Prng.Test public bool IsPredictionResistant { - get - { - return isPredictionResistant; - } + get { return isPredictionResistant; } } public byte[] GetEntropy() { byte[] rv = new byte[bitsRequired / 8]; - Array.Copy(data, index, rv, 0, rv.Length); - index += bitsRequired / 8; - return rv; } public int EntropySize { - get - { - return bitsRequired; - } + get { return bitsRequired; } } + } } } -} diff --git a/crypto/test/src/crypto/prng/test/X931Test.cs b/crypto/test/src/crypto/prng/test/X931Test.cs new file mode 100644 index 000000000..1132ea34a --- /dev/null +++ b/crypto/test/src/crypto/prng/test/X931Test.cs @@ -0,0 +1,137 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Prng.Test +{ + /** + * HMAC SP800-90 DRBG + */ + [TestFixture] + public class X931Test + : SimpleTest + { + public override string Name + { + get { return "X931"; } + } + + public static void Main(string[] args) + { + RunTest(new X931Test()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + + private X931TestVector[] CreateTestVectorData() + { + return new X931TestVector[] + { + new X931TestVector( + new AesEngine(), + new Aes128EntropyProvider(), + "f7d36762b9915f1ed585eb8e91700eb2", + "259e67249288597a4d61e7c0e690afae", + false, + new string[] + { + "15f013af5a8e9df9a8e37500edaeac43", + "a9d74bb1c90a222adc398546d64879cf", + "0379e404042d58180764fb9e6c5d94bb", + "3c74603e036d28c79947ffb56fee4e51", + "e872101a4df81ebbe1e632fc87195d52", + "26a6b3d33b8e7e68b75d9630ec036314" + }), + new X931TestVector( + new DesEdeEngine(), + new TDesEntropyProvider(), + "ef16ec643e5db5892cbc6eabba310b3410e6f8759e3e382c", + "55df103deaf68dc4", + false, + new string[] + { + "9c960bb9662ce6de", + "d9d0e527fd0931da", + "3e2db9994e9e6995", + "0e3868aef8218cf7", + "7b0b0ca137f8fd81", + "f657df270ad12265" + }) + }; + } + + public override void PerformTest() + { + X931TestVector[] vectors = CreateTestVectorData(); + + for (int i = 0; i != vectors.Length; i++) + { + X931TestVector tv = vectors[i]; + X931SecureRandomBuilder bld = new X931SecureRandomBuilder(tv.EntropyProvider); + + bld.SetDateTimeVector(Hex.Decode(tv.DateTimeVector)); + + SecureRandom rand = bld.Build(tv.Engine, new KeyParameter(Hex.Decode(tv.Key)), tv.IsPredictionResistant); + + for (int j = 0; j != tv.Expected.Length - 1; j++) + { + byte[] expected = Hex.Decode(tv.Expected[j]); + byte[] res = new byte[expected.Length]; + + rand.NextBytes(res); + + if (!Arrays.AreEqual(expected, res)) + { + Fail("expected output wrong [" + j + "] got : " + Strings.FromByteArray(Hex.Encode(res))); + } + } + + { + byte[] expected = Hex.Decode(tv.Expected[tv.Expected.Length - 1]); + byte[] res = new byte[expected.Length]; + + for (int j = tv.Expected.Length - 1; j != 10000; j++) + { + rand.NextBytes(res); + } + + if (!Arrays.AreEqual(expected, res)) + { + Fail("expected output wrong [" + 10000 + "] got : " + Strings.FromByteArray(Hex.Encode(res))); + } + } + } + } + + private class Aes128EntropyProvider + : TestEntropySourceProvider + { + internal Aes128EntropyProvider() + : base(Hex.Decode("35cc0ea481fc8a4f5f05c7d4667233b2"), true) + { + } + } + + private class TDesEntropyProvider + : TestEntropySourceProvider + { + internal TDesEntropyProvider() + : base(Hex.Decode("96d872b9122c5e74"), true) + { + } + } + } +} diff --git a/crypto/test/src/crypto/prng/test/X931TestVector.cs b/crypto/test/src/crypto/prng/test/X931TestVector.cs new file mode 100644 index 000000000..e641b0a66 --- /dev/null +++ b/crypto/test/src/crypto/prng/test/X931TestVector.cs @@ -0,0 +1,55 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Prng.Test +{ + public class X931TestVector + { + private readonly IBlockCipher engine; + private readonly IEntropySourceProvider entropyProvider; + private readonly string key; + private readonly string dateTimeVector; + private readonly bool predictionResistant; + private readonly string[] expected; + + public X931TestVector(IBlockCipher engine, IEntropySourceProvider entropyProvider, string key, string dateTimeVector, + bool predictionResistant, string[] expected) + { + this.engine = engine; + this.entropyProvider = entropyProvider; + this.key = key; + this.dateTimeVector = dateTimeVector; + this.predictionResistant = predictionResistant; + this.expected = expected; + } + + public string DateTimeVector + { + get { return dateTimeVector; } + } + + public IBlockCipher Engine + { + get { return engine; } + } + + public IEntropySourceProvider EntropyProvider + { + get { return entropyProvider; } + } + + public string[] Expected + { + get { return expected; } + } + + public string Key + { + get { return key; } + } + + public bool IsPredictionResistant + { + get { return predictionResistant; } + } + } +} -- cgit 1.5.1 From ced92a086526c85e31842aaa60ede4c4b8e0fdb9 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Tue, 17 Nov 2015 18:57:14 +0700 Subject: Improve usage/behaviour of SecureRandom.GenerateSeed --- crypto/crypto.csproj | 10 ++++ crypto/src/crypto/CipherKeyGenerator.cs | 4 +- crypto/src/crypto/encodings/OaepEncoding.cs | 2 +- .../crypto/prng/CryptoApiEntropySourceProvider.cs | 70 ++++++++++++++++++++++ crypto/src/crypto/prng/DigestRandomGenerator.cs | 12 ++-- crypto/src/crypto/prng/EntropyUtilities.cs | 30 ++++++++++ crypto/src/crypto/prng/SP800SecureRandom.cs | 4 +- crypto/src/crypto/prng/X931Rng.cs | 2 +- crypto/src/crypto/prng/X931SecureRandom.cs | 4 +- crypto/src/security/SecureRandom.cs | 21 +++---- crypto/test/src/security/test/SecureRandomTest.cs | 41 ++++++++++++- crypto/test/src/test/BlockCipherTest.cs | 2 +- crypto/test/src/util/test/FixedSecureRandom.cs | 7 ++- 13 files changed, 178 insertions(+), 31 deletions(-) create mode 100644 crypto/src/crypto/prng/CryptoApiEntropySourceProvider.cs create mode 100644 crypto/src/crypto/prng/EntropyUtilities.cs (limited to 'crypto/test/src') diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index 395ea08df..ecfdc7311 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -4318,6 +4318,11 @@ SubType = "Code" BuildAction = "Compile" /> + + >= 8; - } + byte[] bytes = new byte[8]; + Pack.UInt64_To_LE((ulong)seedVal, bytes); + digest.BlockUpdate(bytes, 0, bytes.Length); } - private void DigestUpdate(byte[] inSeed) + private void DigestUpdate(byte[] inSeed) { digest.BlockUpdate(inSeed, 0, inSeed.Length); } diff --git a/crypto/src/crypto/prng/EntropyUtilities.cs b/crypto/src/crypto/prng/EntropyUtilities.cs new file mode 100644 index 000000000..58c8703f4 --- /dev/null +++ b/crypto/src/crypto/prng/EntropyUtilities.cs @@ -0,0 +1,30 @@ +using System; + +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Prng +{ + public abstract class EntropyUtilities + { + /** + * Generate numBytes worth of entropy from the passed in entropy source. + * + * @param entropySource the entropy source to request the data from. + * @param numBytes the number of bytes of entropy requested. + * @return a byte array populated with the random data. + */ + public static byte[] GenerateSeed(IEntropySource entropySource, int numBytes) + { + byte[] bytes = new byte[numBytes]; + int count = 0; + while (count < numBytes) + { + byte[] entropy = entropySource.GetEntropy(); + int toCopy = System.Math.Min(bytes.Length, numBytes - count); + Array.Copy(entropy, 0, bytes, count, toCopy); + count += toCopy; + } + return bytes; + } + } +} diff --git a/crypto/src/crypto/prng/SP800SecureRandom.cs b/crypto/src/crypto/prng/SP800SecureRandom.cs index 996ba0846..5c5bda399 100644 --- a/crypto/src/crypto/prng/SP800SecureRandom.cs +++ b/crypto/src/crypto/prng/SP800SecureRandom.cs @@ -74,9 +74,7 @@ namespace Org.BouncyCastle.Crypto.Prng public override byte[] GenerateSeed(int numBytes) { - byte[] bytes = new byte[numBytes]; - NextBytes(bytes); - return bytes; + return EntropyUtilities.GenerateSeed(mEntropySource, numBytes); } } } diff --git a/crypto/src/crypto/prng/X931Rng.cs b/crypto/src/crypto/prng/X931Rng.cs index d09cc6618..987379d4b 100644 --- a/crypto/src/crypto/prng/X931Rng.cs +++ b/crypto/src/crypto/prng/X931Rng.cs @@ -10,7 +10,7 @@ namespace Org.BouncyCastle.Crypto.Prng private const int BLOCK128_MAX_BITS_REQUEST = 1 << (19 - 1); private readonly IBlockCipher mEngine; - private readonly IEntropySource mEntropySource; + internal readonly IEntropySource mEntropySource; private readonly byte[] mDT; private readonly byte[] mI; diff --git a/crypto/src/crypto/prng/X931SecureRandom.cs b/crypto/src/crypto/prng/X931SecureRandom.cs index a87bf1567..bce8d2cf1 100644 --- a/crypto/src/crypto/prng/X931SecureRandom.cs +++ b/crypto/src/crypto/prng/X931SecureRandom.cs @@ -64,9 +64,7 @@ namespace Org.BouncyCastle.Crypto.Prng public override byte[] GenerateSeed(int numBytes) { - byte[] bytes = new byte[numBytes]; - NextBytes(bytes); - return bytes; + return EntropyUtilities.GenerateSeed(mDrbg.mEntropySource, numBytes); } } } diff --git a/crypto/src/security/SecureRandom.cs b/crypto/src/security/SecureRandom.cs index 8683b4729..cb831acc2 100644 --- a/crypto/src/security/SecureRandom.cs +++ b/crypto/src/security/SecureRandom.cs @@ -68,11 +68,18 @@ namespace Org.BouncyCastle.Security if (autoSeed) { prng.AddSeedMaterial(NextCounterValue()); - prng.AddSeedMaterial(GetSeed(digest.GetDigestSize())); + prng.AddSeedMaterial(GetNextBytes(Master, digest.GetDigestSize())); } return prng; } + public static byte[] GetNextBytes(SecureRandom secureRandom, int length) + { + byte[] result = new byte[length]; + secureRandom.NextBytes(result); + return result; + } + ///

    /// Create and auto-seed an instance based on the given algorithm. /// @@ -104,12 +111,10 @@ namespace Org.BouncyCastle.Security throw new ArgumentException("Unrecognised PRNG algorithm: " + algorithm, "algorithm"); } + [Obsolete("Call GenerateSeed() on a SecureRandom instance instead")] public static byte[] GetSeed(int length) { -#if NETCF_1_0 || PORTABLE - lock (master) -#endif - return Master.GenerateSeed(length); + return GetNextBytes(Master, length); } protected readonly IRandomGenerator generator; @@ -145,11 +150,7 @@ namespace Org.BouncyCastle.Security public virtual byte[] GenerateSeed(int length) { - SetSeed(DateTime.Now.Ticks); - - byte[] rv = new byte[length]; - NextBytes(rv); - return rv; + return GetNextBytes(Master, length); } public virtual void SetSeed(byte[] seed) diff --git a/crypto/test/src/security/test/SecureRandomTest.cs b/crypto/test/src/security/test/SecureRandomTest.cs index f93afc0aa..f1d83b29c 100644 --- a/crypto/test/src/security/test/SecureRandomTest.cs +++ b/crypto/test/src/security/test/SecureRandomTest.cs @@ -3,7 +3,12 @@ using System.Text; using NUnit.Framework; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Macs; using Org.BouncyCastle.Crypto.Prng; +using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Security.Tests @@ -60,6 +65,30 @@ namespace Org.BouncyCastle.Security.Tests CheckSecureRandom(random); } + [Test] + public void TestSP800Ctr() + { + SecureRandom random = new SP800SecureRandomBuilder().BuildCtr(new AesFastEngine(), 256, new byte[32], false); + + CheckSecureRandom(random); + } + + [Test] + public void TestSP800Hash() + { + SecureRandom random = new SP800SecureRandomBuilder().BuildHash(new Sha256Digest(), new byte[32], false); + + CheckSecureRandom(random); + } + + [Test] + public void TestSP800HMac() + { + SecureRandom random = new SP800SecureRandomBuilder().BuildHMac(new HMac(new Sha256Digest()), new byte[32], false); + + CheckSecureRandom(random); + } + [Test] public void TestThreadedSeed() { @@ -73,7 +102,15 @@ namespace Org.BouncyCastle.Security.Tests public void TestVmpcPrng() { SecureRandom random = new SecureRandom(new VmpcRandomGenerator()); - random.SetSeed(SecureRandom.GetSeed(32)); + random.SetSeed(random.GenerateSeed(32)); + + CheckSecureRandom(random); + } + + [Test] + public void TestX931() + { + SecureRandom random = new X931SecureRandomBuilder().Build(new AesFastEngine(), new KeyParameter(new byte[16]), false); CheckSecureRandom(random); } @@ -106,7 +143,7 @@ namespace Org.BouncyCastle.Security.Tests private static double MeasureChiSquared(SecureRandom random, int rounds) { - byte[] opts = SecureRandom.GetSeed(2); + byte[] opts = random.GenerateSeed(2); int[] counts = new int[256]; byte[] bs = new byte[256]; diff --git a/crypto/test/src/test/BlockCipherTest.cs b/crypto/test/src/test/BlockCipherTest.cs index 93cf2b0a5..fc3a99f4e 100644 --- a/crypto/test/src/test/BlockCipherTest.cs +++ b/crypto/test/src/test/BlockCipherTest.cs @@ -410,7 +410,7 @@ namespace Org.BouncyCastle.Tests else { // NB: rand always generates same values each test run - iv = rand.GenerateSeed(ivLength); + iv = SecureRandom.GetNextBytes(rand, ivLength); } parameters = new ParametersWithIV(key, iv); diff --git a/crypto/test/src/util/test/FixedSecureRandom.cs b/crypto/test/src/util/test/FixedSecureRandom.cs index 15a2e9bb3..d8598ac24 100644 --- a/crypto/test/src/util/test/FixedSecureRandom.cs +++ b/crypto/test/src/util/test/FixedSecureRandom.cs @@ -38,7 +38,12 @@ namespace Org.BouncyCastle.Utilities.Test return new FixedSecureRandom(bOut.ToArray()); } - public override void NextBytes( + public override byte[] GenerateSeed(int numBytes) + { + return SecureRandom.GetNextBytes(this, numBytes); + } + + public override void NextBytes( byte[] buf) { Array.Copy(_data, _index, buf, 0, buf.Length); -- cgit 1.5.1 From 6e86f37d4008e5cf9cd410fcc3e43e5420915ed7 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sat, 21 Nov 2015 14:25:02 +0700 Subject: BMA-52 Fix SerpentEngine byte-ordering - The new TnepresEngine was added to retain the historical behaviour of SerpentEngine --- crypto/crypto.csproj | 15 + crypto/src/crypto/engines/SerpentEngine.cs | 565 ++----------------------- crypto/src/crypto/engines/SerpentEngineBase.cs | 467 ++++++++++++++++++++ crypto/src/crypto/engines/TnepresEngine.cs | 299 +++++++++++++ crypto/src/security/CipherUtilities.cs | 5 + crypto/src/security/GeneratorUtilities.cs | 3 +- crypto/src/security/ParameterUtilities.cs | 1 + crypto/test/src/crypto/test/RegressionTest.cs | 1 + crypto/test/src/crypto/test/SerpentTest.cs | 181 ++++---- crypto/test/src/crypto/test/TnepresTest.cs | 155 +++++++ crypto/test/src/test/BlockCipherTest.cs | 125 +++++- 11 files changed, 1213 insertions(+), 604 deletions(-) create mode 100644 crypto/src/crypto/engines/SerpentEngineBase.cs create mode 100644 crypto/src/crypto/engines/TnepresEngine.cs create mode 100644 crypto/test/src/crypto/test/TnepresTest.cs (limited to 'crypto/test/src') diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index 1685c54d9..572a3cce5 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -3643,6 +3643,11 @@ SubType = "Code" BuildAction = "Compile" /> + + + - * Serpent was designed by Ross Anderson, Eli Biham and Lars Knudsen as a - * candidate algorithm for the NIST AES Quest.> - *

    - *

    - * For full details see the The Serpent home page - *

    + * Serpent is a 128-bit 32-round block cipher with variable key lengths, + * including 128, 192 and 256 bit keys conjectured to be at least as + * secure as three-key triple-DES. + *

    + * Serpent was designed by Ross Anderson, Eli Biham and Lars Knudsen as a + * candidate algorithm for the NIST AES Quest. + *

    + *

    + * For full details see The Serpent home page + *

    */ - public class SerpentEngine - : IBlockCipher + public sealed class SerpentEngine + : SerpentEngineBase { - private const int BLOCK_SIZE = 16; - - static readonly int ROUNDS = 32; - static readonly int PHI = unchecked((int)0x9E3779B9); // (Sqrt(5) - 1) * 2**31 - - private bool encrypting; - private int[] wKey; - - private int X0, X1, X2, X3; // registers - - /** - * initialise a Serpent cipher. - * - * @param forEncryption whether or not we are for encryption. - * @param parameters the parameters required to set up the cipher. - * @exception ArgumentException if the parameters argument is - * inappropriate. - */ - public virtual void Init( - bool forEncryption, - ICipherParameters parameters) - { - if (!(parameters is KeyParameter)) - throw new ArgumentException("invalid parameter passed to Serpent init - " + parameters.GetType().ToString()); - - this.encrypting = forEncryption; - this.wKey = MakeWorkingKey(((KeyParameter)parameters).GetKey()); - } - - public virtual string AlgorithmName - { - get { return "Serpent"; } - } - - public virtual bool IsPartialBlockOkay - { - get { return false; } - } - - public virtual int GetBlockSize() - { - return BLOCK_SIZE; - } - - /** - * Process one block of input from the array in and write it to - * the out array. - * - * @param in the array containing the input data. - * @param inOff offset into the in array the data starts at. - * @param out the array the output data will be copied into. - * @param outOff the offset into the out array the output will start at. - * @exception DataLengthException if there isn't enough data in in, or - * space in out. - * @exception InvalidOperationException if the cipher isn't initialised. - * @return the number of bytes processed and produced. - */ - public virtual int ProcessBlock( - byte[] input, - int inOff, - byte[] output, - int outOff) - { - if (wKey == null) - throw new InvalidOperationException("Serpent not initialised"); - - Check.DataLength(input, inOff, BLOCK_SIZE, "input buffer too short"); - Check.OutputLength(output, outOff, BLOCK_SIZE, "output buffer too short"); - - if (encrypting) - { - EncryptBlock(input, inOff, output, outOff); - } - else - { - DecryptBlock(input, inOff, output, outOff); - } - - return BLOCK_SIZE; - } - - public virtual void Reset() - { - } - /** * Expand a user-supplied key material into a session key. * * @param key The user-key bytes (multiples of 4) to use. * @exception ArgumentException */ - private int[] MakeWorkingKey( - byte[] key) + protected override int[] MakeWorkingKey(byte[] key) { // // pad key to 256 bits @@ -120,14 +35,14 @@ namespace Org.BouncyCastle.Crypto.Engines int off = 0; int length = 0; - for (off = key.Length - 4; off > 0; off -= 4) + for (off = 0; (off + 4) < key.Length; off += 4) { - kPad[length++] = BytesToWord(key, off); + kPad[length++] = (int)Pack.LE_To_UInt32(key, off); } - if (off == 0) + if (off % 4 == 0) { - kPad[length++] = BytesToWord(key, 0); + kPad[length++] = (int)Pack.LE_To_UInt32(key, off); if (length < 8) { kPad[length] = 1; @@ -235,57 +150,20 @@ namespace Org.BouncyCastle.Crypto.Engines return w; } - private int RotateLeft( - int x, - int bits) - { - return ((x << bits) | (int) ((uint)x >> (32 - bits))); - } - - private int RotateRight( - int x, - int bits) - { - return ( (int)((uint)x >> bits) | (x << (32 - bits))); - } - - private int BytesToWord( - byte[] src, - int srcOff) - { - return (((src[srcOff] & 0xff) << 24) | ((src[srcOff + 1] & 0xff) << 16) | - ((src[srcOff + 2] & 0xff) << 8) | ((src[srcOff + 3] & 0xff))); - } - - private void WordToBytes( - int word, - byte[] dst, - int dstOff) - { - dst[dstOff + 3] = (byte)(word); - dst[dstOff + 2] = (byte)((uint)word >> 8); - dst[dstOff + 1] = (byte)((uint)word >> 16); - dst[dstOff] = (byte)((uint)word >> 24); - } - /** * Encrypt one block of plaintext. * - * @param in the array containing the input data. + * @param input the array containing the input data. * @param inOff offset into the in array the data starts at. - * @param out the array the output data will be copied into. + * @param output the array the output data will be copied into. * @param outOff the offset into the out array the output will start at. */ - private void EncryptBlock( - byte[] input, - int inOff, - byte[] outBytes, - int outOff) + protected override void EncryptBlock(byte[] input, int inOff, byte[] output, int outOff) { - X3 = BytesToWord(input, inOff); - X2 = BytesToWord(input, inOff + 4); - X1 = BytesToWord(input, inOff + 8); - X0 = BytesToWord(input, inOff + 12); + X0 = (int)Pack.LE_To_UInt32(input, inOff); + X1 = (int)Pack.LE_To_UInt32(input, inOff + 4); + X2 = (int)Pack.LE_To_UInt32(input, inOff + 8); + X3 = (int)Pack.LE_To_UInt32(input, inOff + 12); Sb0(wKey[0] ^ X0, wKey[1] ^ X1, wKey[2] ^ X2, wKey[3] ^ X3); LT(); Sb1(wKey[4] ^ X0, wKey[5] ^ X1, wKey[6] ^ X2, wKey[7] ^ X3); LT(); @@ -320,30 +198,26 @@ namespace Org.BouncyCastle.Crypto.Engines Sb6(wKey[120] ^ X0, wKey[121] ^ X1, wKey[122] ^ X2, wKey[123] ^ X3); LT(); Sb7(wKey[124] ^ X0, wKey[125] ^ X1, wKey[126] ^ X2, wKey[127] ^ X3); - WordToBytes(wKey[131] ^ X3, outBytes, outOff); - WordToBytes(wKey[130] ^ X2, outBytes, outOff + 4); - WordToBytes(wKey[129] ^ X1, outBytes, outOff + 8); - WordToBytes(wKey[128] ^ X0, outBytes, outOff + 12); + Pack.UInt32_To_LE((uint)(wKey[128] ^ X0), output, outOff); + Pack.UInt32_To_LE((uint)(wKey[129] ^ X1), output, outOff + 4); + Pack.UInt32_To_LE((uint)(wKey[130] ^ X2), output, outOff + 8); + Pack.UInt32_To_LE((uint)(wKey[131] ^ X3), output, outOff + 12); } /** * Decrypt one block of ciphertext. * - * @param in the array containing the input data. + * @param input the array containing the input data. * @param inOff offset into the in array the data starts at. - * @param out the array the output data will be copied into. + * @param output the array the output data will be copied into. * @param outOff the offset into the out array the output will start at. */ - private void DecryptBlock( - byte[] input, - int inOff, - byte[] outBytes, - int outOff) + protected override void DecryptBlock(byte[] input, int inOff, byte[] output, int outOff) { - X3 = wKey[131] ^ BytesToWord(input, inOff); - X2 = wKey[130] ^ BytesToWord(input, inOff + 4); - X1 = wKey[129] ^ BytesToWord(input, inOff + 8); - X0 = wKey[128] ^ BytesToWord(input, inOff + 12); + X0 = wKey[128] ^ (int)Pack.LE_To_UInt32(input, inOff); + X1 = wKey[129] ^ (int)Pack.LE_To_UInt32(input, inOff + 4); + X2 = wKey[130] ^ (int)Pack.LE_To_UInt32(input, inOff + 8); + X3 = wKey[131] ^ (int)Pack.LE_To_UInt32(input, inOff + 12); Ib7(X0, X1, X2, X3); X0 ^= wKey[124]; X1 ^= wKey[125]; X2 ^= wKey[126]; X3 ^= wKey[127]; @@ -409,369 +283,10 @@ namespace Org.BouncyCastle.Crypto.Engines X0 ^= wKey[4]; X1 ^= wKey[5]; X2 ^= wKey[6]; X3 ^= wKey[7]; InverseLT(); Ib0(X0, X1, X2, X3); - WordToBytes(X3 ^ wKey[3], outBytes, outOff); - WordToBytes(X2 ^ wKey[2], outBytes, outOff + 4); - WordToBytes(X1 ^ wKey[1], outBytes, outOff + 8); - WordToBytes(X0 ^ wKey[0], outBytes, outOff + 12); - } - - /* - * The sboxes below are based on the work of Brian Gladman and - * Sam Simpson, whose original notice appears below. - *

    - * For further details see: - * http://fp.gladman.plus.com/cryptography_technology/serpent/ - *

    - */ - - /* Partially optimised Serpent S Box bool functions derived */ - /* using a recursive descent analyser but without a full search */ - /* of all subtrees. This set of S boxes is the result of work */ - /* by Sam Simpson and Brian Gladman using the spare time on a */ - /* cluster of high capacity servers to search for S boxes with */ - /* this customised search engine. There are now an average of */ - /* 15.375 terms per S box. */ - /* */ - /* Copyright: Dr B. R Gladman (gladman@seven77.demon.co.uk) */ - /* and Sam Simpson (s.simpson@mia.co.uk) */ - /* 17th December 1998 */ - /* */ - /* We hereby give permission for information in this file to be */ - /* used freely subject only to acknowledgement of its origin. */ - - /** - * S0 - { 3, 8,15, 1,10, 6, 5,11,14,13, 4, 2, 7, 0, 9,12 } - 15 terms. - */ - private void Sb0(int a, int b, int c, int d) - { - int t1 = a ^ d; - int t3 = c ^ t1; - int t4 = b ^ t3; - X3 = (a & d) ^ t4; - int t7 = a ^ (b & t1); - X2 = t4 ^ (c | t7); - int t12 = X3 & (t3 ^ t7); - X1 = (~t3) ^ t12; - X0 = t12 ^ (~t7); - } - - /** - * InvSO - {13, 3,11, 0,10, 6, 5,12, 1,14, 4, 7,15, 9, 8, 2 } - 15 terms. - */ - private void Ib0(int a, int b, int c, int d) - { - int t1 = ~a; - int t2 = a ^ b; - int t4 = d ^ (t1 | t2); - int t5 = c ^ t4; - X2 = t2 ^ t5; - int t8 = t1 ^ (d & t2); - X1 = t4 ^ (X2 & t8); - X3 = (a & t4) ^ (t5 | X1); - X0 = X3 ^ (t5 ^ t8); - } - - /** - * S1 - {15,12, 2, 7, 9, 0, 5,10, 1,11,14, 8, 6,13, 3, 4 } - 14 terms. - */ - private void Sb1(int a, int b, int c, int d) - { - int t2 = b ^ (~a); - int t5 = c ^ (a | t2); - X2 = d ^ t5; - int t7 = b ^ (d | t2); - int t8 = t2 ^ X2; - X3 = t8 ^ (t5 & t7); - int t11 = t5 ^ t7; - X1 = X3 ^ t11; - X0 = t5 ^ (t8 & t11); - } - - /** - * InvS1 - { 5, 8, 2,14,15, 6,12, 3,11, 4, 7, 9, 1,13,10, 0 } - 14 steps. - */ - private void Ib1(int a, int b, int c, int d) - { - int t1 = b ^ d; - int t3 = a ^ (b & t1); - int t4 = t1 ^ t3; - X3 = c ^ t4; - int t7 = b ^ (t1 & t3); - int t8 = X3 | t7; - X1 = t3 ^ t8; - int t10 = ~X1; - int t11 = X3 ^ t7; - X0 = t10 ^ t11; - X2 = t4 ^ (t10 | t11); - } - - /** - * S2 - { 8, 6, 7, 9, 3,12,10,15,13, 1,14, 4, 0,11, 5, 2 } - 16 terms. - */ - private void Sb2(int a, int b, int c, int d) - { - int t1 = ~a; - int t2 = b ^ d; - int t3 = c & t1; - X0 = t2 ^ t3; - int t5 = c ^ t1; - int t6 = c ^ X0; - int t7 = b & t6; - X3 = t5 ^ t7; - X2 = a ^ ((d | t7) & (X0 | t5)); - X1 = (t2 ^ X3) ^ (X2 ^ (d | t1)); - } - - /** - * InvS2 - {12, 9,15, 4,11,14, 1, 2, 0, 3, 6,13, 5, 8,10, 7 } - 16 steps. - */ - private void Ib2(int a, int b, int c, int d) - { - int t1 = b ^ d; - int t2 = ~t1; - int t3 = a ^ c; - int t4 = c ^ t1; - int t5 = b & t4; - X0 = t3 ^ t5; - int t7 = a | t2; - int t8 = d ^ t7; - int t9 = t3 | t8; - X3 = t1 ^ t9; - int t11 = ~t4; - int t12 = X0 | X3; - X1 = t11 ^ t12; - X2 = (d & t11) ^ (t3 ^ t12); - } - - /** - * S3 - { 0,15,11, 8,12, 9, 6, 3,13, 1, 2, 4,10, 7, 5,14 } - 16 terms. - */ - private void Sb3(int a, int b, int c, int d) - { - int t1 = a ^ b; - int t2 = a & c; - int t3 = a | d; - int t4 = c ^ d; - int t5 = t1 & t3; - int t6 = t2 | t5; - X2 = t4 ^ t6; - int t8 = b ^ t3; - int t9 = t6 ^ t8; - int t10 = t4 & t9; - X0 = t1 ^ t10; - int t12 = X2 & X0; - X1 = t9 ^ t12; - X3 = (b | d) ^ (t4 ^ t12); - } - - /** - * InvS3 - { 0, 9,10, 7,11,14, 6,13, 3, 5,12, 2, 4, 8,15, 1 } - 15 terms - */ - private void Ib3(int a, int b, int c, int d) - { - int t1 = a | b; - int t2 = b ^ c; - int t3 = b & t2; - int t4 = a ^ t3; - int t5 = c ^ t4; - int t6 = d | t4; - X0 = t2 ^ t6; - int t8 = t2 | t6; - int t9 = d ^ t8; - X2 = t5 ^ t9; - int t11 = t1 ^ t9; - int t12 = X0 & t11; - X3 = t4 ^ t12; - X1 = X3 ^ (X0 ^ t11); - } - - /** - * S4 - { 1,15, 8, 3,12, 0,11, 6, 2, 5, 4,10, 9,14, 7,13 } - 15 terms. - */ - private void Sb4(int a, int b, int c, int d) - { - int t1 = a ^ d; - int t2 = d & t1; - int t3 = c ^ t2; - int t4 = b | t3; - X3 = t1 ^ t4; - int t6 = ~b; - int t7 = t1 | t6; - X0 = t3 ^ t7; - int t9 = a & X0; - int t10 = t1 ^ t6; - int t11 = t4 & t10; - X2 = t9 ^ t11; - X1 = (a ^ t3) ^ (t10 & X2); - } - - /** - * InvS4 - { 5, 0, 8, 3,10, 9, 7,14, 2,12,11, 6, 4,15,13, 1 } - 15 terms. - */ - private void Ib4(int a, int b, int c, int d) - { - int t1 = c | d; - int t2 = a & t1; - int t3 = b ^ t2; - int t4 = a & t3; - int t5 = c ^ t4; - X1 = d ^ t5; - int t7 = ~a; - int t8 = t5 & X1; - X3 = t3 ^ t8; - int t10 = X1 | t7; - int t11 = d ^ t10; - X0 = X3 ^ t11; - X2 = (t3 & t11) ^ (X1 ^ t7); - } - - /** - * S5 - {15, 5, 2,11, 4,10, 9,12, 0, 3,14, 8,13, 6, 7, 1 } - 16 terms. - */ - private void Sb5(int a, int b, int c, int d) - { - int t1 = ~a; - int t2 = a ^ b; - int t3 = a ^ d; - int t4 = c ^ t1; - int t5 = t2 | t3; - X0 = t4 ^ t5; - int t7 = d & X0; - int t8 = t2 ^ X0; - X1 = t7 ^ t8; - int t10 = t1 | X0; - int t11 = t2 | t7; - int t12 = t3 ^ t10; - X2 = t11 ^ t12; - X3 = (b ^ t7) ^ (X1 & t12); - } - - /** - * InvS5 - { 8,15, 2, 9, 4, 1,13,14,11, 6, 5, 3, 7,12,10, 0 } - 16 terms. - */ - private void Ib5(int a, int b, int c, int d) - { - int t1 = ~c; - int t2 = b & t1; - int t3 = d ^ t2; - int t4 = a & t3; - int t5 = b ^ t1; - X3 = t4 ^ t5; - int t7 = b | X3; - int t8 = a & t7; - X1 = t3 ^ t8; - int t10 = a | d; - int t11 = t1 ^ t7; - X0 = t10 ^ t11; - X2 = (b & t10) ^ (t4 | (a ^ c)); - } - - /** - * S6 - { 7, 2,12, 5, 8, 4, 6,11,14, 9, 1,15,13, 3,10, 0 } - 15 terms. - */ - private void Sb6(int a, int b, int c, int d) - { - int t1 = ~a; - int t2 = a ^ d; - int t3 = b ^ t2; - int t4 = t1 | t2; - int t5 = c ^ t4; - X1 = b ^ t5; - int t7 = t2 | X1; - int t8 = d ^ t7; - int t9 = t5 & t8; - X2 = t3 ^ t9; - int t11 = t5 ^ t8; - X0 = X2 ^ t11; - X3 = (~t5) ^ (t3 & t11); - } - - /** - * InvS6 - {15,10, 1,13, 5, 3, 6, 0, 4, 9,14, 7, 2,12, 8,11 } - 15 terms. - */ - private void Ib6(int a, int b, int c, int d) - { - int t1 = ~a; - int t2 = a ^ b; - int t3 = c ^ t2; - int t4 = c | t1; - int t5 = d ^ t4; - X1 = t3 ^ t5; - int t7 = t3 & t5; - int t8 = t2 ^ t7; - int t9 = b | t8; - X3 = t5 ^ t9; - int t11 = b | X3; - X0 = t8 ^ t11; - X2 = (d & t1) ^ (t3 ^ t11); - } - - /** - * S7 - { 1,13,15, 0,14, 8, 2,11, 7, 4,12,10, 9, 3, 5, 6 } - 16 terms. - */ - private void Sb7(int a, int b, int c, int d) - { - int t1 = b ^ c; - int t2 = c & t1; - int t3 = d ^ t2; - int t4 = a ^ t3; - int t5 = d | t1; - int t6 = t4 & t5; - X1 = b ^ t6; - int t8 = t3 | X1; - int t9 = a & t4; - X3 = t1 ^ t9; - int t11 = t4 ^ t8; - int t12 = X3 & t11; - X2 = t3 ^ t12; - X0 = (~t11) ^ (X3 & X2); - } - - /** - * InvS7 - { 3, 0, 6,13, 9,14,15, 8, 5,12,11, 7,10, 1, 4, 2 } - 17 terms. - */ - private void Ib7(int a, int b, int c, int d) - { - int t3 = c | (a & b); - int t4 = d & (a | b); - X3 = t3 ^ t4; - int t6 = ~d; - int t7 = b ^ t4; - int t9 = t7 | (X3 ^ t6); - X1 = a ^ t9; - X0 = (c ^ t7) ^ (d | X1); - X2 = (t3 ^ X1) ^ (X0 ^ (a & X3)); - } - - /** - * Apply the linear transformation to the register set. - */ - private void LT() - { - int x0 = RotateLeft(X0, 13); - int x2 = RotateLeft(X2, 3); - int x1 = X1 ^ x0 ^ x2 ; - int x3 = X3 ^ x2 ^ x0 << 3; - - X1 = RotateLeft(x1, 1); - X3 = RotateLeft(x3, 7); - X0 = RotateLeft(x0 ^ X1 ^ X3, 5); - X2 = RotateLeft(x2 ^ X3 ^ (X1 << 7), 22); - } - - /** - * Apply the inverse of the linear transformation to the register set. - */ - private void InverseLT() - { - int x2 = RotateRight(X2, 22) ^ X3 ^ (X1 << 7); - int x0 = RotateRight(X0, 5) ^ X1 ^ X3; - int x3 = RotateRight(X3, 7); - int x1 = RotateRight(X1, 1); - X3 = x3 ^ x2 ^ x0 << 3; - X1 = x1 ^ x0 ^ x2; - X2 = RotateRight(x2, 3); - X0 = RotateRight(x0, 13); + Pack.UInt32_To_LE((uint)(X0 ^ wKey[0]), output, outOff); + Pack.UInt32_To_LE((uint)(X1 ^ wKey[1]), output, outOff + 4); + Pack.UInt32_To_LE((uint)(X2 ^ wKey[2]), output, outOff + 8); + Pack.UInt32_To_LE((uint)(X3 ^ wKey[3]), output, outOff + 12); } } } diff --git a/crypto/src/crypto/engines/SerpentEngineBase.cs b/crypto/src/crypto/engines/SerpentEngineBase.cs new file mode 100644 index 000000000..a4c686922 --- /dev/null +++ b/crypto/src/crypto/engines/SerpentEngineBase.cs @@ -0,0 +1,467 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Engines +{ + public abstract class SerpentEngineBase + : IBlockCipher + { + protected static readonly int BlockSize = 16; + + internal const int ROUNDS = 32; + internal const int PHI = unchecked((int)0x9E3779B9); // (sqrt(5) - 1) * 2**31 + + protected bool encrypting; + protected int[] wKey; + + protected int X0, X1, X2, X3; // registers + + protected SerpentEngineBase() + { + } + + /** + * initialise a Serpent cipher. + * + * @param encrypting whether or not we are for encryption. + * @param params the parameters required to set up the cipher. + * @throws IllegalArgumentException if the params argument is + * inappropriate. + */ + public virtual void Init(bool encrypting, ICipherParameters parameters) + { + if (!(parameters is KeyParameter)) + throw new ArgumentException("invalid parameter passed to " + AlgorithmName + " init - " + parameters.GetType().ToString()); + + this.encrypting = encrypting; + this.wKey = MakeWorkingKey(((KeyParameter)parameters).GetKey()); + } + + public virtual string AlgorithmName + { + get { return "Serpent"; } + } + + public virtual bool IsPartialBlockOkay + { + get { return false; } + } + + public virtual int GetBlockSize() + { + return BlockSize; + } + + /** + * Process one block of input from the array in and write it to + * the out array. + * + * @param in the array containing the input data. + * @param inOff offset into the in array the data starts at. + * @param out the array the output data will be copied into. + * @param outOff the offset into the out array the output will start at. + * @return the number of bytes processed and produced. + * @throws DataLengthException if there isn't enough data in in, or + * space in out. + * @throws IllegalStateException if the cipher isn't initialised. + */ + public int ProcessBlock(byte[] input, int inOff, byte[] output, int outOff) + { + if (wKey == null) + throw new InvalidOperationException(AlgorithmName + " not initialised"); + + Check.DataLength(input, inOff, BlockSize, "input buffer too short"); + Check.OutputLength(output, outOff, BlockSize, "output buffer too short"); + + if (encrypting) + { + EncryptBlock(input, inOff, output, outOff); + } + else + { + DecryptBlock(input, inOff, output, outOff); + } + + return BlockSize; + } + + public virtual void Reset() + { + } + + protected static int RotateLeft(int x, int bits) + { + return ((x << bits) | (int) ((uint)x >> (32 - bits))); + } + + private static int RotateRight(int x, int bits) + { + return ( (int)((uint)x >> bits) | (x << (32 - bits))); + } + + /** + * The sboxes below are based on the work of Brian Gladman and + * Sam Simpson, whose original notice appears below. + *

    + * For further details see: + * http://fp.gladman.plus.com/cryptography_technology/serpent/ + */ + + /* Partially optimised Serpent S Box boolean functions derived */ + /* using a recursive descent analyser but without a full search */ + /* of all subtrees. This set of S boxes is the result of work */ + /* by Sam Simpson and Brian Gladman using the spare time on a */ + /* cluster of high capacity servers to search for S boxes with */ + /* this customised search engine. There are now an average of */ + /* 15.375 terms per S box. */ + /* */ + /* Copyright: Dr B. R Gladman (gladman@seven77.demon.co.uk) */ + /* and Sam Simpson (s.simpson@mia.co.uk) */ + /* 17th December 1998 */ + /* */ + /* We hereby give permission for information in this file to be */ + /* used freely subject only to acknowledgement of its origin. */ + + /** + * S0 - { 3, 8,15, 1,10, 6, 5,11,14,13, 4, 2, 7, 0, 9,12 } - 15 terms. + */ + protected void Sb0(int a, int b, int c, int d) + { + int t1 = a ^ d; + int t3 = c ^ t1; + int t4 = b ^ t3; + X3 = (a & d) ^ t4; + int t7 = a ^ (b & t1); + X2 = t4 ^ (c | t7); + int t12 = X3 & (t3 ^ t7); + X1 = (~t3) ^ t12; + X0 = t12 ^ (~t7); + } + + /** + * InvSO - {13, 3,11, 0,10, 6, 5,12, 1,14, 4, 7,15, 9, 8, 2 } - 15 terms. + */ + protected void Ib0(int a, int b, int c, int d) + { + int t1 = ~a; + int t2 = a ^ b; + int t4 = d ^ (t1 | t2); + int t5 = c ^ t4; + X2 = t2 ^ t5; + int t8 = t1 ^ (d & t2); + X1 = t4 ^ (X2 & t8); + X3 = (a & t4) ^ (t5 | X1); + X0 = X3 ^ (t5 ^ t8); + } + + /** + * S1 - {15,12, 2, 7, 9, 0, 5,10, 1,11,14, 8, 6,13, 3, 4 } - 14 terms. + */ + protected void Sb1(int a, int b, int c, int d) + { + int t2 = b ^ (~a); + int t5 = c ^ (a | t2); + X2 = d ^ t5; + int t7 = b ^ (d | t2); + int t8 = t2 ^ X2; + X3 = t8 ^ (t5 & t7); + int t11 = t5 ^ t7; + X1 = X3 ^ t11; + X0 = t5 ^ (t8 & t11); + } + + /** + * InvS1 - { 5, 8, 2,14,15, 6,12, 3,11, 4, 7, 9, 1,13,10, 0 } - 14 steps. + */ + protected void Ib1(int a, int b, int c, int d) + { + int t1 = b ^ d; + int t3 = a ^ (b & t1); + int t4 = t1 ^ t3; + X3 = c ^ t4; + int t7 = b ^ (t1 & t3); + int t8 = X3 | t7; + X1 = t3 ^ t8; + int t10 = ~X1; + int t11 = X3 ^ t7; + X0 = t10 ^ t11; + X2 = t4 ^ (t10 | t11); + } + + /** + * S2 - { 8, 6, 7, 9, 3,12,10,15,13, 1,14, 4, 0,11, 5, 2 } - 16 terms. + */ + protected void Sb2(int a, int b, int c, int d) + { + int t1 = ~a; + int t2 = b ^ d; + int t3 = c & t1; + X0 = t2 ^ t3; + int t5 = c ^ t1; + int t6 = c ^ X0; + int t7 = b & t6; + X3 = t5 ^ t7; + X2 = a ^ ((d | t7) & (X0 | t5)); + X1 = (t2 ^ X3) ^ (X2 ^ (d | t1)); + } + + /** + * InvS2 - {12, 9,15, 4,11,14, 1, 2, 0, 3, 6,13, 5, 8,10, 7 } - 16 steps. + */ + protected void Ib2(int a, int b, int c, int d) + { + int t1 = b ^ d; + int t2 = ~t1; + int t3 = a ^ c; + int t4 = c ^ t1; + int t5 = b & t4; + X0 = t3 ^ t5; + int t7 = a | t2; + int t8 = d ^ t7; + int t9 = t3 | t8; + X3 = t1 ^ t9; + int t11 = ~t4; + int t12 = X0 | X3; + X1 = t11 ^ t12; + X2 = (d & t11) ^ (t3 ^ t12); + } + + /** + * S3 - { 0,15,11, 8,12, 9, 6, 3,13, 1, 2, 4,10, 7, 5,14 } - 16 terms. + */ + protected void Sb3(int a, int b, int c, int d) + { + int t1 = a ^ b; + int t2 = a & c; + int t3 = a | d; + int t4 = c ^ d; + int t5 = t1 & t3; + int t6 = t2 | t5; + X2 = t4 ^ t6; + int t8 = b ^ t3; + int t9 = t6 ^ t8; + int t10 = t4 & t9; + X0 = t1 ^ t10; + int t12 = X2 & X0; + X1 = t9 ^ t12; + X3 = (b | d) ^ (t4 ^ t12); + } + + /** + * InvS3 - { 0, 9,10, 7,11,14, 6,13, 3, 5,12, 2, 4, 8,15, 1 } - 15 terms + */ + protected void Ib3(int a, int b, int c, int d) + { + int t1 = a | b; + int t2 = b ^ c; + int t3 = b & t2; + int t4 = a ^ t3; + int t5 = c ^ t4; + int t6 = d | t4; + X0 = t2 ^ t6; + int t8 = t2 | t6; + int t9 = d ^ t8; + X2 = t5 ^ t9; + int t11 = t1 ^ t9; + int t12 = X0 & t11; + X3 = t4 ^ t12; + X1 = X3 ^ (X0 ^ t11); + } + + /** + * S4 - { 1,15, 8, 3,12, 0,11, 6, 2, 5, 4,10, 9,14, 7,13 } - 15 terms. + */ + protected void Sb4(int a, int b, int c, int d) + { + int t1 = a ^ d; + int t2 = d & t1; + int t3 = c ^ t2; + int t4 = b | t3; + X3 = t1 ^ t4; + int t6 = ~b; + int t7 = t1 | t6; + X0 = t3 ^ t7; + int t9 = a & X0; + int t10 = t1 ^ t6; + int t11 = t4 & t10; + X2 = t9 ^ t11; + X1 = (a ^ t3) ^ (t10 & X2); + } + + /** + * InvS4 - { 5, 0, 8, 3,10, 9, 7,14, 2,12,11, 6, 4,15,13, 1 } - 15 terms. + */ + protected void Ib4(int a, int b, int c, int d) + { + int t1 = c | d; + int t2 = a & t1; + int t3 = b ^ t2; + int t4 = a & t3; + int t5 = c ^ t4; + X1 = d ^ t5; + int t7 = ~a; + int t8 = t5 & X1; + X3 = t3 ^ t8; + int t10 = X1 | t7; + int t11 = d ^ t10; + X0 = X3 ^ t11; + X2 = (t3 & t11) ^ (X1 ^ t7); + } + + /** + * S5 - {15, 5, 2,11, 4,10, 9,12, 0, 3,14, 8,13, 6, 7, 1 } - 16 terms. + */ + protected void Sb5(int a, int b, int c, int d) + { + int t1 = ~a; + int t2 = a ^ b; + int t3 = a ^ d; + int t4 = c ^ t1; + int t5 = t2 | t3; + X0 = t4 ^ t5; + int t7 = d & X0; + int t8 = t2 ^ X0; + X1 = t7 ^ t8; + int t10 = t1 | X0; + int t11 = t2 | t7; + int t12 = t3 ^ t10; + X2 = t11 ^ t12; + X3 = (b ^ t7) ^ (X1 & t12); + } + + /** + * InvS5 - { 8,15, 2, 9, 4, 1,13,14,11, 6, 5, 3, 7,12,10, 0 } - 16 terms. + */ + protected void Ib5(int a, int b, int c, int d) + { + int t1 = ~c; + int t2 = b & t1; + int t3 = d ^ t2; + int t4 = a & t3; + int t5 = b ^ t1; + X3 = t4 ^ t5; + int t7 = b | X3; + int t8 = a & t7; + X1 = t3 ^ t8; + int t10 = a | d; + int t11 = t1 ^ t7; + X0 = t10 ^ t11; + X2 = (b & t10) ^ (t4 | (a ^ c)); + } + + /** + * S6 - { 7, 2,12, 5, 8, 4, 6,11,14, 9, 1,15,13, 3,10, 0 } - 15 terms. + */ + protected void Sb6(int a, int b, int c, int d) + { + int t1 = ~a; + int t2 = a ^ d; + int t3 = b ^ t2; + int t4 = t1 | t2; + int t5 = c ^ t4; + X1 = b ^ t5; + int t7 = t2 | X1; + int t8 = d ^ t7; + int t9 = t5 & t8; + X2 = t3 ^ t9; + int t11 = t5 ^ t8; + X0 = X2 ^ t11; + X3 = (~t5) ^ (t3 & t11); + } + + /** + * InvS6 - {15,10, 1,13, 5, 3, 6, 0, 4, 9,14, 7, 2,12, 8,11 } - 15 terms. + */ + protected void Ib6(int a, int b, int c, int d) + { + int t1 = ~a; + int t2 = a ^ b; + int t3 = c ^ t2; + int t4 = c | t1; + int t5 = d ^ t4; + X1 = t3 ^ t5; + int t7 = t3 & t5; + int t8 = t2 ^ t7; + int t9 = b | t8; + X3 = t5 ^ t9; + int t11 = b | X3; + X0 = t8 ^ t11; + X2 = (d & t1) ^ (t3 ^ t11); + } + + /** + * S7 - { 1,13,15, 0,14, 8, 2,11, 7, 4,12,10, 9, 3, 5, 6 } - 16 terms. + */ + protected void Sb7(int a, int b, int c, int d) + { + int t1 = b ^ c; + int t2 = c & t1; + int t3 = d ^ t2; + int t4 = a ^ t3; + int t5 = d | t1; + int t6 = t4 & t5; + X1 = b ^ t6; + int t8 = t3 | X1; + int t9 = a & t4; + X3 = t1 ^ t9; + int t11 = t4 ^ t8; + int t12 = X3 & t11; + X2 = t3 ^ t12; + X0 = (~t11) ^ (X3 & X2); + } + + /** + * InvS7 - { 3, 0, 6,13, 9,14,15, 8, 5,12,11, 7,10, 1, 4, 2 } - 17 terms. + */ + protected void Ib7(int a, int b, int c, int d) + { + int t3 = c | (a & b); + int t4 = d & (a | b); + X3 = t3 ^ t4; + int t6 = ~d; + int t7 = b ^ t4; + int t9 = t7 | (X3 ^ t6); + X1 = a ^ t9; + X0 = (c ^ t7) ^ (d | X1); + X2 = (t3 ^ X1) ^ (X0 ^ (a & X3)); + } + + /** + * Apply the linear transformation to the register set. + */ + protected void LT() + { + int x0 = RotateLeft(X0, 13); + int x2 = RotateLeft(X2, 3); + int x1 = X1 ^ x0 ^ x2; + int x3 = X3 ^ x2 ^ x0 << 3; + + X1 = RotateLeft(x1, 1); + X3 = RotateLeft(x3, 7); + X0 = RotateLeft(x0 ^ X1 ^ X3, 5); + X2 = RotateLeft(x2 ^ X3 ^ (X1 << 7), 22); + } + + /** + * Apply the inverse of the linear transformation to the register set. + */ + protected void InverseLT() + { + int x2 = RotateRight(X2, 22) ^ X3 ^ (X1 << 7); + int x0 = RotateRight(X0, 5) ^ X1 ^ X3; + int x3 = RotateRight(X3, 7); + int x1 = RotateRight(X1, 1); + X3 = x3 ^ x2 ^ x0 << 3; + X1 = x1 ^ x0 ^ x2; + X2 = RotateRight(x2, 3); + X0 = RotateRight(x0, 13); + } + + protected abstract int[] MakeWorkingKey(byte[] key); + + protected abstract void EncryptBlock(byte[] input, int inOff, byte[] output, int outOff); + + protected abstract void DecryptBlock(byte[] input, int inOff, byte[] output, int outOff); + } +} diff --git a/crypto/src/crypto/engines/TnepresEngine.cs b/crypto/src/crypto/engines/TnepresEngine.cs new file mode 100644 index 000000000..ce687d1e5 --- /dev/null +++ b/crypto/src/crypto/engines/TnepresEngine.cs @@ -0,0 +1,299 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Engines +{ + /** + * Tnepres is a 128-bit 32-round block cipher with variable key lengths, + * including 128, 192 and 256 bit keys conjectured to be at least as + * secure as three-key triple-DES. + *

    + * Tnepres is based on Serpent which was designed by Ross Anderson, Eli Biham and Lars Knudsen as a + * candidate algorithm for the NIST AES Quest. Unfortunately there was an endianness issue + * with test vectors in the AES submission and the resulting confusion lead to the Tnepres cipher + * as well, which is a byte swapped version of Serpent. + *

    + *

    + * For full details see The Serpent home page + *

    + */ + public sealed class TnepresEngine + : SerpentEngineBase + { + public override string AlgorithmName + { + get { return "Tnepres"; } + } + + /** + * Expand a user-supplied key material into a session key. + * + * @param key The user-key bytes (multiples of 4) to use. + * @exception ArgumentException + */ + protected override int[] MakeWorkingKey(byte[] key) + { + // + // pad key to 256 bits + // + int[] kPad = new int[16]; + int off = 0; + int length = 0; + + for (off = key.Length - 4; off > 0; off -= 4) + { + kPad[length++] = (int)Pack.BE_To_UInt32(key, off); + } + + if (off == 0) + { + kPad[length++] = (int)Pack.BE_To_UInt32(key, 0); + if (length < 8) + { + kPad[length] = 1; + } + } + else + { + throw new ArgumentException("key must be a multiple of 4 bytes"); + } + + // + // expand the padded key up to 33 x 128 bits of key material + // + int amount = (ROUNDS + 1) * 4; + int[] w = new int[amount]; + + // + // compute w0 to w7 from w-8 to w-1 + // + for (int i = 8; i < 16; i++) + { + kPad[i] = RotateLeft(kPad[i - 8] ^ kPad[i - 5] ^ kPad[i - 3] ^ kPad[i - 1] ^ PHI ^ (i - 8), 11); + } + + Array.Copy(kPad, 8, w, 0, 8); + + // + // compute w8 to w136 + // + for (int i = 8; i < amount; i++) + { + w[i] = RotateLeft(w[i - 8] ^ w[i - 5] ^ w[i - 3] ^ w[i - 1] ^ PHI ^ i, 11); + } + + // + // create the working keys by processing w with the Sbox and IP + // + Sb3(w[0], w[1], w[2], w[3]); + w[0] = X0; w[1] = X1; w[2] = X2; w[3] = X3; + Sb2(w[4], w[5], w[6], w[7]); + w[4] = X0; w[5] = X1; w[6] = X2; w[7] = X3; + Sb1(w[8], w[9], w[10], w[11]); + w[8] = X0; w[9] = X1; w[10] = X2; w[11] = X3; + Sb0(w[12], w[13], w[14], w[15]); + w[12] = X0; w[13] = X1; w[14] = X2; w[15] = X3; + Sb7(w[16], w[17], w[18], w[19]); + w[16] = X0; w[17] = X1; w[18] = X2; w[19] = X3; + Sb6(w[20], w[21], w[22], w[23]); + w[20] = X0; w[21] = X1; w[22] = X2; w[23] = X3; + Sb5(w[24], w[25], w[26], w[27]); + w[24] = X0; w[25] = X1; w[26] = X2; w[27] = X3; + Sb4(w[28], w[29], w[30], w[31]); + w[28] = X0; w[29] = X1; w[30] = X2; w[31] = X3; + Sb3(w[32], w[33], w[34], w[35]); + w[32] = X0; w[33] = X1; w[34] = X2; w[35] = X3; + Sb2(w[36], w[37], w[38], w[39]); + w[36] = X0; w[37] = X1; w[38] = X2; w[39] = X3; + Sb1(w[40], w[41], w[42], w[43]); + w[40] = X0; w[41] = X1; w[42] = X2; w[43] = X3; + Sb0(w[44], w[45], w[46], w[47]); + w[44] = X0; w[45] = X1; w[46] = X2; w[47] = X3; + Sb7(w[48], w[49], w[50], w[51]); + w[48] = X0; w[49] = X1; w[50] = X2; w[51] = X3; + Sb6(w[52], w[53], w[54], w[55]); + w[52] = X0; w[53] = X1; w[54] = X2; w[55] = X3; + Sb5(w[56], w[57], w[58], w[59]); + w[56] = X0; w[57] = X1; w[58] = X2; w[59] = X3; + Sb4(w[60], w[61], w[62], w[63]); + w[60] = X0; w[61] = X1; w[62] = X2; w[63] = X3; + Sb3(w[64], w[65], w[66], w[67]); + w[64] = X0; w[65] = X1; w[66] = X2; w[67] = X3; + Sb2(w[68], w[69], w[70], w[71]); + w[68] = X0; w[69] = X1; w[70] = X2; w[71] = X3; + Sb1(w[72], w[73], w[74], w[75]); + w[72] = X0; w[73] = X1; w[74] = X2; w[75] = X3; + Sb0(w[76], w[77], w[78], w[79]); + w[76] = X0; w[77] = X1; w[78] = X2; w[79] = X3; + Sb7(w[80], w[81], w[82], w[83]); + w[80] = X0; w[81] = X1; w[82] = X2; w[83] = X3; + Sb6(w[84], w[85], w[86], w[87]); + w[84] = X0; w[85] = X1; w[86] = X2; w[87] = X3; + Sb5(w[88], w[89], w[90], w[91]); + w[88] = X0; w[89] = X1; w[90] = X2; w[91] = X3; + Sb4(w[92], w[93], w[94], w[95]); + w[92] = X0; w[93] = X1; w[94] = X2; w[95] = X3; + Sb3(w[96], w[97], w[98], w[99]); + w[96] = X0; w[97] = X1; w[98] = X2; w[99] = X3; + Sb2(w[100], w[101], w[102], w[103]); + w[100] = X0; w[101] = X1; w[102] = X2; w[103] = X3; + Sb1(w[104], w[105], w[106], w[107]); + w[104] = X0; w[105] = X1; w[106] = X2; w[107] = X3; + Sb0(w[108], w[109], w[110], w[111]); + w[108] = X0; w[109] = X1; w[110] = X2; w[111] = X3; + Sb7(w[112], w[113], w[114], w[115]); + w[112] = X0; w[113] = X1; w[114] = X2; w[115] = X3; + Sb6(w[116], w[117], w[118], w[119]); + w[116] = X0; w[117] = X1; w[118] = X2; w[119] = X3; + Sb5(w[120], w[121], w[122], w[123]); + w[120] = X0; w[121] = X1; w[122] = X2; w[123] = X3; + Sb4(w[124], w[125], w[126], w[127]); + w[124] = X0; w[125] = X1; w[126] = X2; w[127] = X3; + Sb3(w[128], w[129], w[130], w[131]); + w[128] = X0; w[129] = X1; w[130] = X2; w[131] = X3; + + return w; + } + + /** + * Encrypt one block of plaintext. + * + * @param input the array containing the input data. + * @param inOff offset into the in array the data starts at. + * @param output the array the output data will be copied into. + * @param outOff the offset into the out array the output will start at. + */ + protected override void EncryptBlock(byte[] input, int inOff, byte[] output, int outOff) + { + X3 = (int)Pack.BE_To_UInt32(input, inOff); + X2 = (int)Pack.BE_To_UInt32(input, inOff + 4); + X1 = (int)Pack.BE_To_UInt32(input, inOff + 8); + X0 = (int)Pack.BE_To_UInt32(input, inOff + 12); + + Sb0(wKey[0] ^ X0, wKey[1] ^ X1, wKey[2] ^ X2, wKey[3] ^ X3); LT(); + Sb1(wKey[4] ^ X0, wKey[5] ^ X1, wKey[6] ^ X2, wKey[7] ^ X3); LT(); + Sb2(wKey[8] ^ X0, wKey[9] ^ X1, wKey[10] ^ X2, wKey[11] ^ X3); LT(); + Sb3(wKey[12] ^ X0, wKey[13] ^ X1, wKey[14] ^ X2, wKey[15] ^ X3); LT(); + Sb4(wKey[16] ^ X0, wKey[17] ^ X1, wKey[18] ^ X2, wKey[19] ^ X3); LT(); + Sb5(wKey[20] ^ X0, wKey[21] ^ X1, wKey[22] ^ X2, wKey[23] ^ X3); LT(); + Sb6(wKey[24] ^ X0, wKey[25] ^ X1, wKey[26] ^ X2, wKey[27] ^ X3); LT(); + Sb7(wKey[28] ^ X0, wKey[29] ^ X1, wKey[30] ^ X2, wKey[31] ^ X3); LT(); + Sb0(wKey[32] ^ X0, wKey[33] ^ X1, wKey[34] ^ X2, wKey[35] ^ X3); LT(); + Sb1(wKey[36] ^ X0, wKey[37] ^ X1, wKey[38] ^ X2, wKey[39] ^ X3); LT(); + Sb2(wKey[40] ^ X0, wKey[41] ^ X1, wKey[42] ^ X2, wKey[43] ^ X3); LT(); + Sb3(wKey[44] ^ X0, wKey[45] ^ X1, wKey[46] ^ X2, wKey[47] ^ X3); LT(); + Sb4(wKey[48] ^ X0, wKey[49] ^ X1, wKey[50] ^ X2, wKey[51] ^ X3); LT(); + Sb5(wKey[52] ^ X0, wKey[53] ^ X1, wKey[54] ^ X2, wKey[55] ^ X3); LT(); + Sb6(wKey[56] ^ X0, wKey[57] ^ X1, wKey[58] ^ X2, wKey[59] ^ X3); LT(); + Sb7(wKey[60] ^ X0, wKey[61] ^ X1, wKey[62] ^ X2, wKey[63] ^ X3); LT(); + Sb0(wKey[64] ^ X0, wKey[65] ^ X1, wKey[66] ^ X2, wKey[67] ^ X3); LT(); + Sb1(wKey[68] ^ X0, wKey[69] ^ X1, wKey[70] ^ X2, wKey[71] ^ X3); LT(); + Sb2(wKey[72] ^ X0, wKey[73] ^ X1, wKey[74] ^ X2, wKey[75] ^ X3); LT(); + Sb3(wKey[76] ^ X0, wKey[77] ^ X1, wKey[78] ^ X2, wKey[79] ^ X3); LT(); + Sb4(wKey[80] ^ X0, wKey[81] ^ X1, wKey[82] ^ X2, wKey[83] ^ X3); LT(); + Sb5(wKey[84] ^ X0, wKey[85] ^ X1, wKey[86] ^ X2, wKey[87] ^ X3); LT(); + Sb6(wKey[88] ^ X0, wKey[89] ^ X1, wKey[90] ^ X2, wKey[91] ^ X3); LT(); + Sb7(wKey[92] ^ X0, wKey[93] ^ X1, wKey[94] ^ X2, wKey[95] ^ X3); LT(); + Sb0(wKey[96] ^ X0, wKey[97] ^ X1, wKey[98] ^ X2, wKey[99] ^ X3); LT(); + Sb1(wKey[100] ^ X0, wKey[101] ^ X1, wKey[102] ^ X2, wKey[103] ^ X3); LT(); + Sb2(wKey[104] ^ X0, wKey[105] ^ X1, wKey[106] ^ X2, wKey[107] ^ X3); LT(); + Sb3(wKey[108] ^ X0, wKey[109] ^ X1, wKey[110] ^ X2, wKey[111] ^ X3); LT(); + Sb4(wKey[112] ^ X0, wKey[113] ^ X1, wKey[114] ^ X2, wKey[115] ^ X3); LT(); + Sb5(wKey[116] ^ X0, wKey[117] ^ X1, wKey[118] ^ X2, wKey[119] ^ X3); LT(); + Sb6(wKey[120] ^ X0, wKey[121] ^ X1, wKey[122] ^ X2, wKey[123] ^ X3); LT(); + Sb7(wKey[124] ^ X0, wKey[125] ^ X1, wKey[126] ^ X2, wKey[127] ^ X3); + + Pack.UInt32_To_BE((uint)(wKey[131] ^ X3), output, outOff); + Pack.UInt32_To_BE((uint)(wKey[130] ^ X2), output, outOff + 4); + Pack.UInt32_To_BE((uint)(wKey[129] ^ X1), output, outOff + 8); + Pack.UInt32_To_BE((uint)(wKey[128] ^ X0), output, outOff + 12); + } + + /** + * Decrypt one block of ciphertext. + * + * @param input the array containing the input data. + * @param inOff offset into the in array the data starts at. + * @param output the array the output data will be copied into. + * @param outOff the offset into the out array the output will start at. + */ + protected override void DecryptBlock(byte[] input, int inOff, byte[] output, int outOff) + { + X3 = wKey[131] ^ (int)Pack.BE_To_UInt32(input, inOff); + X2 = wKey[130] ^ (int)Pack.BE_To_UInt32(input, inOff + 4); + X1 = wKey[129] ^ (int)Pack.BE_To_UInt32(input, inOff + 8); + X0 = wKey[128] ^ (int)Pack.BE_To_UInt32(input, inOff + 12); + + Ib7(X0, X1, X2, X3); + X0 ^= wKey[124]; X1 ^= wKey[125]; X2 ^= wKey[126]; X3 ^= wKey[127]; + InverseLT(); Ib6(X0, X1, X2, X3); + X0 ^= wKey[120]; X1 ^= wKey[121]; X2 ^= wKey[122]; X3 ^= wKey[123]; + InverseLT(); Ib5(X0, X1, X2, X3); + X0 ^= wKey[116]; X1 ^= wKey[117]; X2 ^= wKey[118]; X3 ^= wKey[119]; + InverseLT(); Ib4(X0, X1, X2, X3); + X0 ^= wKey[112]; X1 ^= wKey[113]; X2 ^= wKey[114]; X3 ^= wKey[115]; + InverseLT(); Ib3(X0, X1, X2, X3); + X0 ^= wKey[108]; X1 ^= wKey[109]; X2 ^= wKey[110]; X3 ^= wKey[111]; + InverseLT(); Ib2(X0, X1, X2, X3); + X0 ^= wKey[104]; X1 ^= wKey[105]; X2 ^= wKey[106]; X3 ^= wKey[107]; + InverseLT(); Ib1(X0, X1, X2, X3); + X0 ^= wKey[100]; X1 ^= wKey[101]; X2 ^= wKey[102]; X3 ^= wKey[103]; + InverseLT(); Ib0(X0, X1, X2, X3); + X0 ^= wKey[96]; X1 ^= wKey[97]; X2 ^= wKey[98]; X3 ^= wKey[99]; + InverseLT(); Ib7(X0, X1, X2, X3); + X0 ^= wKey[92]; X1 ^= wKey[93]; X2 ^= wKey[94]; X3 ^= wKey[95]; + InverseLT(); Ib6(X0, X1, X2, X3); + X0 ^= wKey[88]; X1 ^= wKey[89]; X2 ^= wKey[90]; X3 ^= wKey[91]; + InverseLT(); Ib5(X0, X1, X2, X3); + X0 ^= wKey[84]; X1 ^= wKey[85]; X2 ^= wKey[86]; X3 ^= wKey[87]; + InverseLT(); Ib4(X0, X1, X2, X3); + X0 ^= wKey[80]; X1 ^= wKey[81]; X2 ^= wKey[82]; X3 ^= wKey[83]; + InverseLT(); Ib3(X0, X1, X2, X3); + X0 ^= wKey[76]; X1 ^= wKey[77]; X2 ^= wKey[78]; X3 ^= wKey[79]; + InverseLT(); Ib2(X0, X1, X2, X3); + X0 ^= wKey[72]; X1 ^= wKey[73]; X2 ^= wKey[74]; X3 ^= wKey[75]; + InverseLT(); Ib1(X0, X1, X2, X3); + X0 ^= wKey[68]; X1 ^= wKey[69]; X2 ^= wKey[70]; X3 ^= wKey[71]; + InverseLT(); Ib0(X0, X1, X2, X3); + X0 ^= wKey[64]; X1 ^= wKey[65]; X2 ^= wKey[66]; X3 ^= wKey[67]; + InverseLT(); Ib7(X0, X1, X2, X3); + X0 ^= wKey[60]; X1 ^= wKey[61]; X2 ^= wKey[62]; X3 ^= wKey[63]; + InverseLT(); Ib6(X0, X1, X2, X3); + X0 ^= wKey[56]; X1 ^= wKey[57]; X2 ^= wKey[58]; X3 ^= wKey[59]; + InverseLT(); Ib5(X0, X1, X2, X3); + X0 ^= wKey[52]; X1 ^= wKey[53]; X2 ^= wKey[54]; X3 ^= wKey[55]; + InverseLT(); Ib4(X0, X1, X2, X3); + X0 ^= wKey[48]; X1 ^= wKey[49]; X2 ^= wKey[50]; X3 ^= wKey[51]; + InverseLT(); Ib3(X0, X1, X2, X3); + X0 ^= wKey[44]; X1 ^= wKey[45]; X2 ^= wKey[46]; X3 ^= wKey[47]; + InverseLT(); Ib2(X0, X1, X2, X3); + X0 ^= wKey[40]; X1 ^= wKey[41]; X2 ^= wKey[42]; X3 ^= wKey[43]; + InverseLT(); Ib1(X0, X1, X2, X3); + X0 ^= wKey[36]; X1 ^= wKey[37]; X2 ^= wKey[38]; X3 ^= wKey[39]; + InverseLT(); Ib0(X0, X1, X2, X3); + X0 ^= wKey[32]; X1 ^= wKey[33]; X2 ^= wKey[34]; X3 ^= wKey[35]; + InverseLT(); Ib7(X0, X1, X2, X3); + X0 ^= wKey[28]; X1 ^= wKey[29]; X2 ^= wKey[30]; X3 ^= wKey[31]; + InverseLT(); Ib6(X0, X1, X2, X3); + X0 ^= wKey[24]; X1 ^= wKey[25]; X2 ^= wKey[26]; X3 ^= wKey[27]; + InverseLT(); Ib5(X0, X1, X2, X3); + X0 ^= wKey[20]; X1 ^= wKey[21]; X2 ^= wKey[22]; X3 ^= wKey[23]; + InverseLT(); Ib4(X0, X1, X2, X3); + X0 ^= wKey[16]; X1 ^= wKey[17]; X2 ^= wKey[18]; X3 ^= wKey[19]; + InverseLT(); Ib3(X0, X1, X2, X3); + X0 ^= wKey[12]; X1 ^= wKey[13]; X2 ^= wKey[14]; X3 ^= wKey[15]; + InverseLT(); Ib2(X0, X1, X2, X3); + X0 ^= wKey[8]; X1 ^= wKey[9]; X2 ^= wKey[10]; X3 ^= wKey[11]; + InverseLT(); Ib1(X0, X1, X2, X3); + X0 ^= wKey[4]; X1 ^= wKey[5]; X2 ^= wKey[6]; X3 ^= wKey[7]; + InverseLT(); Ib0(X0, X1, X2, X3); + + Pack.UInt32_To_BE((uint)(X3 ^ wKey[3]), output, outOff); + Pack.UInt32_To_BE((uint)(X2 ^ wKey[2]), output, outOff + 4); + Pack.UInt32_To_BE((uint)(X1 ^ wKey[1]), output, outOff + 8); + Pack.UInt32_To_BE((uint)(X0 ^ wKey[0]), output, outOff + 12); + } + } +} diff --git a/crypto/src/security/CipherUtilities.cs b/crypto/src/security/CipherUtilities.cs index 9ad4228ac..e09eff8d6 100644 --- a/crypto/src/security/CipherUtilities.cs +++ b/crypto/src/security/CipherUtilities.cs @@ -54,6 +54,7 @@ namespace Org.BouncyCastle.Security SERPENT, SKIPJACK, TEA, + TNEPRES, TWOFISH, VMPC, VMPC_KSA3, @@ -432,6 +433,9 @@ namespace Org.BouncyCastle.Security case CipherAlgorithm.TEA: blockCipher = new TeaEngine(); break; + case CipherAlgorithm.TNEPRES: + blockCipher = new TnepresEngine(); + break; case CipherAlgorithm.TWOFISH: blockCipher = new TwofishEngine(); break; @@ -725,6 +729,7 @@ namespace Org.BouncyCastle.Security case CipherAlgorithm.SERPENT: return new SerpentEngine(); case CipherAlgorithm.SKIPJACK: return new SkipjackEngine(); case CipherAlgorithm.TEA: return new TeaEngine(); + case CipherAlgorithm.TNEPRES: return new TnepresEngine(); case CipherAlgorithm.TWOFISH: return new TwofishEngine(); case CipherAlgorithm.XTEA: return new XteaEngine(); default: diff --git a/crypto/src/security/GeneratorUtilities.cs b/crypto/src/security/GeneratorUtilities.cs index 7562a76be..2104a67ba 100644 --- a/crypto/src/security/GeneratorUtilities.cs +++ b/crypto/src/security/GeneratorUtilities.cs @@ -109,6 +109,7 @@ namespace Org.BouncyCastle.Security AddKgAlgorithm("SERPENT"); AddKgAlgorithm("SKIPJACK"); AddKgAlgorithm("TEA"); + AddKgAlgorithm("TNEPRES"); AddKgAlgorithm("TWOFISH"); AddKgAlgorithm("VMPC"); AddKgAlgorithm("VMPC-KSA3"); @@ -178,7 +179,7 @@ namespace Org.BouncyCastle.Security "RC2", "RC4", "RC5", "SALSA20", "SEED", "TEA", "XTEA", "VMPC", "VMPC-KSA3"); AddDefaultKeySizeEntries(160, "HMACRIPEMD160", "HMACSHA1"); AddDefaultKeySizeEntries(192, "AES", "AES192", "CAMELLIA192", "DESEDE3", "HMACTIGER", - "RIJNDAEL", "SERPENT"); + "RIJNDAEL", "SERPENT", "TNEPRES"); AddDefaultKeySizeEntries(224, "HMACSHA224"); AddDefaultKeySizeEntries(256, "AES256", "CAMELLIA", "CAMELLIA256", "CAST6", "GOST28147", "HC256", "HMACSHA256", "RC5-64", "RC6", "TWOFISH"); diff --git a/crypto/src/security/ParameterUtilities.cs b/crypto/src/security/ParameterUtilities.cs index b2d7c0dff..8fc3732f5 100644 --- a/crypto/src/security/ParameterUtilities.cs +++ b/crypto/src/security/ParameterUtilities.cs @@ -104,6 +104,7 @@ namespace Org.BouncyCastle.Security AddAlgorithm("SERPENT"); AddAlgorithm("SKIPJACK"); AddAlgorithm("TEA"); + AddAlgorithm("TNEPRES"); AddAlgorithm("TWOFISH"); AddAlgorithm("VMPC"); AddAlgorithm("VMPC-KSA3"); diff --git a/crypto/test/src/crypto/test/RegressionTest.cs b/crypto/test/src/crypto/test/RegressionTest.cs index ab6394571..ad74cce31 100644 --- a/crypto/test/src/crypto/test/RegressionTest.cs +++ b/crypto/test/src/crypto/test/RegressionTest.cs @@ -34,6 +34,7 @@ namespace Org.BouncyCastle.Crypto.Tests new RC6Test(), new RijndaelTest(), new SerpentTest(), + new TnepresTest(), new CamelliaTest(), new CamelliaLightTest(), new DigestRandomNumberTest(), diff --git a/crypto/test/src/crypto/test/SerpentTest.cs b/crypto/test/src/crypto/test/SerpentTest.cs index 2467797e9..08dbda591 100644 --- a/crypto/test/src/crypto/test/SerpentTest.cs +++ b/crypto/test/src/crypto/test/SerpentTest.cs @@ -4,111 +4,142 @@ using NUnit.Framework; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Engines; -using Org.BouncyCastle.Crypto.Encodings; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Paddings; using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; using Org.BouncyCastle.Utilities.Encoders; using Org.BouncyCastle.Utilities.Test; namespace Org.BouncyCastle.Crypto.Tests { + /** + * Test vectors based on the NESSIE submission + */ [TestFixture] - public class SerpentTest: CipherTest + public class SerpentTest + : CipherTest { - static SimpleTest[] tests = + static SimpleTest[] tests = { new BlockCipherVectorTest(0, new SerpentEngine(), - new KeyParameter(Hex.Decode("0000000000000000000000000000000000000000000000000000000000000000")), - "00000000000000000000000000000000", "8910494504181950f98dd998a82b6749"), - new BlockCipherVectorTest(1, new SerpentEngine(), new KeyParameter(Hex.Decode("00000000000000000000000000000000")), - "80000000000000000000000000000000", "10b5ffb720b8cb9002a1142b0ba2e94a"), + "00000000000000000000000000000000", "3620b17ae6a993d09618b8768266bae9"), + new BlockCipherVectorTest(1, new SerpentEngine(), + new KeyParameter(Hex.Decode("80000000000000000000000000000000")), + "00000000000000000000000000000000", "264E5481EFF42A4606ABDA06C0BFDA3D"), new BlockCipherVectorTest(2, new SerpentEngine(), - new KeyParameter(Hex.Decode("00000000000000000000000000000000")), - "00000000008000000000000000000000", "4f057a42d8d5bd9746e434680ddcd5e5"), + new KeyParameter(Hex.Decode("D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9")), + "D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9", "20EA07F19C8E93FDA30F6B822AD5D486"), new BlockCipherVectorTest(3, new SerpentEngine(), - new KeyParameter(Hex.Decode("00000000000000000000000000000000")), - "00000000000000000000400000000000", "99407bf8582ef12550886ef5b6f169b9"), + new KeyParameter(Hex.Decode("000000000000000000000000000000000000000000008000")), + "00000000000000000000000000000000", "40520018C4AC2BBA285AEEB9BCB58755"), new BlockCipherVectorTest(4, new SerpentEngine(), - new KeyParameter(Hex.Decode("000000000000000000000000000000000000000000000000")), - "40000000000000000000000000000000", "d522a3b8d6d89d4d2a124fdd88f36896"), + new KeyParameter(Hex.Decode("0000000000000000000000000000000000000000000000000000000000000000")), + "00000000000000000000000000000001", "AD86DE83231C3203A86AE33B721EAA9F"), new BlockCipherVectorTest(5, new SerpentEngine(), - new KeyParameter(Hex.Decode("000000000000000000000000000000000000000000000000")), - "00000000000200000000000000000000", "189b8ec3470085b3da97e82ca8964e32"), + new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F")), + "3DA46FFA6F4D6F30CD258333E5A61369", "00112233445566778899AABBCCDDEEFF"), new BlockCipherVectorTest(6, new SerpentEngine(), - new KeyParameter(Hex.Decode("000000000000000000000000000000000000000000000000")), - "00000000000000000000008000000000", "f77d868cf760b9143a89809510ccb099"), + new KeyParameter(Hex.Decode("2BD6459F82C5B300952C49104881FF482BD6459F82C5B300952C49104881FF48")), + "677C8DFAA08071743FD2B415D1B28AF2", "EA024714AD5C4D84EA024714AD5C4D84"), new BlockCipherVectorTest(7, new SerpentEngine(), - new KeyParameter(Hex.Decode("0000000000000000000000000000000000000000000000000000000000000000")), - "08000000000000000000000000000000", "d43b7b981b829342fce0e3ec6f5f4c82"), + new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F1011121314151617")), + "4528CACCB954D450655E8CFD71CBFAC7", "00112233445566778899AABBCCDDEEFF"), new BlockCipherVectorTest(8, new SerpentEngine(), - new KeyParameter(Hex.Decode("0000000000000000000000000000000000000000000000000000000000000000")), - "00000000000000000100000000000000", "0bf30e1a0c33ccf6d5293177886912a7"), + new KeyParameter(Hex.Decode("2BD6459F82C5B300952C49104881FF482BD6459F82C5B300")), + "E0208BE278E21420C4B1B9747788A954", "EA024714AD5C4D84EA024714AD5C4D84"), new BlockCipherVectorTest(9, new SerpentEngine(), - new KeyParameter(Hex.Decode("0000000000000000000000000000000000000000000000000000000000000000")), - "00000000000000000000000000000001", "6a7f3b805d2ddcba49b89770ade5e507"), + new KeyParameter(Hex.Decode("000102030405060708090A0B0C0D0E0F")), + "33B3DC87EDDD9B0F6A1F407D14919365", "00112233445566778899AABBCCDDEEFF"), new BlockCipherVectorTest(10, new SerpentEngine(), - new KeyParameter(Hex.Decode("80000000000000000000000000000000")), - "00000000000000000000000000000000", "49afbfad9d5a34052cd8ffa5986bd2dd"), - new BlockCipherVectorTest(11, new SerpentEngine(), - new KeyParameter(Hex.Decode("000000000000000000000000004000000000000000000000")), - "00000000000000000000000000000000", "ba8829b1de058c4b48615d851fc74f17"), - new BlockCipherVectorTest(12, new SerpentEngine(), - new KeyParameter(Hex.Decode("0000000000000000000000000000000000000000000000000000000100000000")), - "00000000000000000000000000000000", "89f64377bf1e8a46c8247044e8056a98"), -/* - new BlockCipherMonteCarloTest(13, 10000, new SerpentEngine(), - new KeyParameter(Hex.Decode("47f5f881daab9b67b43bd1342e339c19")), - "7a4f7db38c52a8b711b778a38d203b6b", "003380e19f10065740394f48e2fe80b7"), -*/ - new BlockCipherMonteCarloTest(13, 100, new SerpentEngine(), - new KeyParameter(Hex.Decode("47f5f881daab9b67b43bd1342e339c19")), - "7a4f7db38c52a8b711b778a38d203b6b", "4db75303d815c2f7cc6ca935d1c5a046"), -/* - new BlockCipherMonteCarloTest(14, 10000, new SerpentEngine(), - new KeyParameter(Hex.Decode("31fba879ebc5e80df35e6fa33eaf92d6")), - "70a05e12f74589009692a337f53ff614", "afb5425426906db26b70bdf842ac5400"), -*/ - new BlockCipherMonteCarloTest(14, 100, new SerpentEngine(), - new KeyParameter(Hex.Decode("31fba879ebc5e80df35e6fa33eaf92d6")), - "70a05e12f74589009692a337f53ff614", "fc53a50f4d3bc9836001893d2f41742d"), -/* - new BlockCipherMonteCarloTest(15, 10000, new SerpentEngine(), - new KeyParameter(Hex.Decode("bde6dd392307984695aee80e574f9977caae9aa78eda53e8")), - "9cc523d034a93740a0aa4e2054bb34d8", "1949d506ada7de1f1344986e8ea049b2"), -*/ - new BlockCipherMonteCarloTest(15, 100, new SerpentEngine(), - new KeyParameter(Hex.Decode("bde6dd392307984695aee80e574f9977caae9aa78eda53e8")), - "9cc523d034a93740a0aa4e2054bb34d8", "77117e6a9e80f40b2a36b7d755573c2d"), -/* - new BlockCipherMonteCarloTest(16, 10000, new SerpentEngine(), - new KeyParameter(Hex.Decode("60f6f8ad4290699dc50921a1bbcca92da914e7d9cf01a9317c79c0af8f2487a1")), - "ee1a61106fae2d381d686cbf854bab65", "e57f45559027cb1f2ed9603d814e1c34"), -*/ - new BlockCipherMonteCarloTest(16, 100, new SerpentEngine(), - new KeyParameter(Hex.Decode("60f6f8ad4290699dc50921a1bbcca92da914e7d9cf01a9317c79c0af8f2487a1")), - "ee1a61106fae2d381d686cbf854bab65", "dcd7f13ea0dcdfd0139d1a42e2ffb84b") + new KeyParameter(Hex.Decode("2BD6459F82C5B300952C49104881FF48")), + "BEB6C069393822D3BE73FF30525EC43E", "EA024714AD5C4D84EA024714AD5C4D84"), + new BlockCipherMonteCarloTest(20, 100, new SerpentEngine(), + new KeyParameter(Hex.Decode("F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3")), + "F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3", "8FD0E58DB7A54B929FCA6A12F96F20AF"), + new BlockCipherMonteCarloTest(21, 100, new SerpentEngine(), + new KeyParameter(Hex.Decode("0004000000000000000000000000000000000000000000000000000000000000")), + "00000000000000000000000000000000", "E7B681E8871FD05FEAE5FB64DA891EA2"), + new BlockCipherMonteCarloTest(22, 100, new SerpentEngine(), + new KeyParameter(Hex.Decode("0000000020000000000000000000000000000000000000000000000000000000")), + "00000000000000000000000000000000", "C5545D516EEC73BFA3622A8194F95620"), + new BlockCipherMonteCarloTest(23, 100, new SerpentEngine(), + new KeyParameter(Hex.Decode("0000000000000000000000000000000000000000000000000000000002000000")), + "00000000000000000000000000000000", "11FF5C9BE006F82C98BD4FAC1A19920E"), + new BlockCipherMonteCarloTest(24, 100, new SerpentEngine(), + new KeyParameter(Hex.Decode("0000000000000000000000000000000000000000000000000000000000000000")), + "00000000000000000000000000010000", "47CA1CA404B6481CAD4C21C8A0415A0E"), + new BlockCipherMonteCarloTest(25, 100, new SerpentEngine(), + new KeyParameter(Hex.Decode("0000000000000000000000000000000000000000000000000000000000000000")), + "00000000000000008000000000000000", "A0A2D5B07E27D539CA5BEE9DE1EAB3E6") }; - public SerpentTest() - : base(tests, new SerpentEngine(), new KeyParameter(new byte[32])) - { - } + public SerpentTest() + : base(tests, new SerpentEngine(), new KeyParameter(new byte[32])) + { + } - public override string Name + public override void PerformTest() { - get { return "Serpent"; } + base.PerformTest(); + + //DoCbcMonte(new byte[16], new byte[16], new byte[16], Hex.Decode("9ea101ecebaa41c712bcb0d9bab3e2e4")); + //DoCbcMonte(Hex.Decode("9ea101ecebaa41c712bcb0d9bab3e2e4"), Hex.Decode("9ea101ecebaa41c712bcb0d9bab3e2e4"), Hex.Decode("b4813d8a66244188b9e92c75913fa2f4"), Hex.Decode("f86b2c265b9c75869f31e2c684c13e9f")); + + DoCbc(Hex.Decode("BE4295539F6BD1752FD0A80229EF8847"), Hex.Decode("00963F59224794D5AD4252094358FBC3"), Strings.ToByteArray("CBC Mode Test"), Hex.Decode("CF2CF2547E02F6D34D97246E8042ED89")); + + + DoEax(Hex.Decode("7494A57648FB420043BFBFC5639EB82D"), Hex.Decode("6DF94638B83E01458F3E30C9A1D6AF1C"), Strings.ToByteArray("EAX Mode Test"), new byte[0], 128, Hex.Decode("96C521F32DC5E9BBC369DDE4914CB13B710EEBBAB7D706D3ABE06A99DC")); } - public static void Main( - string[] args) + private void DoEax(byte[] key, byte[] iv, byte[] pt, byte[] aad, int tagLength, byte[] expected) { - ITest test = new SerpentTest(); - ITestResult result = test.Perform(); + EaxBlockCipher c = new EaxBlockCipher(new SerpentEngine()); - Console.WriteLine(result); + c.Init(true, new AeadParameters(new KeyParameter(key), tagLength, iv, aad)); + + byte[] output = new byte[expected.Length]; + + int len = c.ProcessBytes(pt, 0, pt.Length, output, 0); + + c.DoFinal(output, len); + + if (!Arrays.AreEqual(expected, output)) + { + Fail("EAX test failed"); + } + } + + private void DoCbc(byte[] key, byte[] iv, byte[] pt, byte[] expected) + { + PaddedBufferedBlockCipher c = new PaddedBufferedBlockCipher(new CbcBlockCipher(new SerpentEngine()), new Pkcs7Padding()); + + byte[] ct = new byte[expected.Length]; + + c.Init(true, new ParametersWithIV(new KeyParameter(key), iv)); + + int l = c.ProcessBytes(pt, 0, pt.Length, ct, 0); + + c.DoFinal(ct, l); + + if (!Arrays.AreEqual(expected, ct)) + { + Fail("CBC test failed"); + } + } + + public override string Name + { + get { return "Serpent"; } + } + + public static void Main(string[] args) + { + RunTest(new SerpentTest()); } - [Test] + [Test] public void TestFunction() { string resultText = Perform().ToString(); diff --git a/crypto/test/src/crypto/test/TnepresTest.cs b/crypto/test/src/crypto/test/TnepresTest.cs new file mode 100644 index 000000000..07308dbff --- /dev/null +++ b/crypto/test/src/crypto/test/TnepresTest.cs @@ -0,0 +1,155 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * Test vectors based on Floppy 4 of the Serpent AES submission. + */ + [TestFixture] + public class TnepresTest + : CipherTest + { + static SimpleTest[] tests = + { + new BlockCipherVectorTest(0, new TnepresEngine(), + new KeyParameter(Hex.Decode("0000000000000000000000000000000000000000000000000000000000000000")), + "00000000000000000000000000000000", "8910494504181950f98dd998a82b6749"), + new BlockCipherVectorTest(1, new TnepresEngine(), + new KeyParameter(Hex.Decode("00000000000000000000000000000000")), + "80000000000000000000000000000000", "10b5ffb720b8cb9002a1142b0ba2e94a"), + new BlockCipherVectorTest(2, new TnepresEngine(), + new KeyParameter(Hex.Decode("00000000000000000000000000000000")), + "00000000008000000000000000000000", "4f057a42d8d5bd9746e434680ddcd5e5"), + new BlockCipherVectorTest(3, new TnepresEngine(), + new KeyParameter(Hex.Decode("00000000000000000000000000000000")), + "00000000000000000000400000000000", "99407bf8582ef12550886ef5b6f169b9"), + new BlockCipherVectorTest(4, new TnepresEngine(), + new KeyParameter(Hex.Decode("000000000000000000000000000000000000000000000000")), + "40000000000000000000000000000000", "d522a3b8d6d89d4d2a124fdd88f36896"), + new BlockCipherVectorTest(5, new TnepresEngine(), + new KeyParameter(Hex.Decode("000000000000000000000000000000000000000000000000")), + "00000000000200000000000000000000", "189b8ec3470085b3da97e82ca8964e32"), + new BlockCipherVectorTest(6, new TnepresEngine(), + new KeyParameter(Hex.Decode("000000000000000000000000000000000000000000000000")), + "00000000000000000000008000000000", "f77d868cf760b9143a89809510ccb099"), + new BlockCipherVectorTest(7, new TnepresEngine(), + new KeyParameter(Hex.Decode("0000000000000000000000000000000000000000000000000000000000000000")), + "08000000000000000000000000000000", "d43b7b981b829342fce0e3ec6f5f4c82"), + new BlockCipherVectorTest(8, new TnepresEngine(), + new KeyParameter(Hex.Decode("0000000000000000000000000000000000000000000000000000000000000000")), + "00000000000000000100000000000000", "0bf30e1a0c33ccf6d5293177886912a7"), + new BlockCipherVectorTest(9, new TnepresEngine(), + new KeyParameter(Hex.Decode("0000000000000000000000000000000000000000000000000000000000000000")), + "00000000000000000000000000000001", "6a7f3b805d2ddcba49b89770ade5e507"), + new BlockCipherVectorTest(10, new TnepresEngine(), + new KeyParameter(Hex.Decode("80000000000000000000000000000000")), + "00000000000000000000000000000000", "49afbfad9d5a34052cd8ffa5986bd2dd"), + new BlockCipherVectorTest(11, new TnepresEngine(), + new KeyParameter(Hex.Decode("000000000000000000000000004000000000000000000000")), + "00000000000000000000000000000000", "ba8829b1de058c4b48615d851fc74f17"), + new BlockCipherVectorTest(12, new TnepresEngine(), + new KeyParameter(Hex.Decode("0000000000000000000000000000000000000000000000000000000100000000")), + "00000000000000000000000000000000", "89f64377bf1e8a46c8247044e8056a98"), +/* + new BlockCipherMonteCarloTest(13, 10000, new TnepresEngine(), + new KeyParameter(Hex.Decode("47f5f881daab9b67b43bd1342e339c19")), + "7a4f7db38c52a8b711b778a38d203b6b", "003380e19f10065740394f48e2fe80b7"), +*/ + new BlockCipherMonteCarloTest(13, 100, new TnepresEngine(), + new KeyParameter(Hex.Decode("47f5f881daab9b67b43bd1342e339c19")), + "7a4f7db38c52a8b711b778a38d203b6b", "4db75303d815c2f7cc6ca935d1c5a046"), +/* + new BlockCipherMonteCarloTest(14, 10000, new TnepresEngine(), + new KeyParameter(Hex.Decode("31fba879ebc5e80df35e6fa33eaf92d6")), + "70a05e12f74589009692a337f53ff614", "afb5425426906db26b70bdf842ac5400"), +*/ + new BlockCipherMonteCarloTest(14, 100, new TnepresEngine(), + new KeyParameter(Hex.Decode("31fba879ebc5e80df35e6fa33eaf92d6")), + "70a05e12f74589009692a337f53ff614", "fc53a50f4d3bc9836001893d2f41742d"), +/* + new BlockCipherMonteCarloTest(15, 10000, new TnepresEngine(), + new KeyParameter(Hex.Decode("bde6dd392307984695aee80e574f9977caae9aa78eda53e8")), + "9cc523d034a93740a0aa4e2054bb34d8", "1949d506ada7de1f1344986e8ea049b2"), +*/ + new BlockCipherMonteCarloTest(15, 100, new TnepresEngine(), + new KeyParameter(Hex.Decode("bde6dd392307984695aee80e574f9977caae9aa78eda53e8")), + "9cc523d034a93740a0aa4e2054bb34d8", "77117e6a9e80f40b2a36b7d755573c2d"), +/* + new BlockCipherMonteCarloTest(16, 10000, new TnepresEngine(), + new KeyParameter(Hex.Decode("60f6f8ad4290699dc50921a1bbcca92da914e7d9cf01a9317c79c0af8f2487a1")), + "ee1a61106fae2d381d686cbf854bab65", "e57f45559027cb1f2ed9603d814e1c34"), +*/ + new BlockCipherMonteCarloTest(16, 100, new TnepresEngine(), + new KeyParameter(Hex.Decode("60f6f8ad4290699dc50921a1bbcca92da914e7d9cf01a9317c79c0af8f2487a1")), + "ee1a61106fae2d381d686cbf854bab65", "dcd7f13ea0dcdfd0139d1a42e2ffb84b") + }; + + public TnepresTest() + : base(tests, new TnepresEngine(), new KeyParameter(new byte[32])) + { + } + + public override void PerformTest() + { + base.PerformTest(); + + DoCbcMonte(new byte[16], new byte[16], new byte[16], Hex.Decode("9ea101ecebaa41c712bcb0d9bab3e2e4")); + DoCbcMonte(Hex.Decode("9ea101ecebaa41c712bcb0d9bab3e2e4"), Hex.Decode("9ea101ecebaa41c712bcb0d9bab3e2e4"), Hex.Decode("b4813d8a66244188b9e92c75913fa2f4"), Hex.Decode("f86b2c265b9c75869f31e2c684c13e9f")); + } + + private void DoCbcMonte(byte[] key, byte[] iv, byte[] pt, byte[] expected) + { + IBlockCipher c = new TnepresEngine(); + + byte[] ct = new byte[16]; + + Array.Copy(iv, 0, ct, 0, 16); + + for (int i = 0; i < 10000; i++) + { + for (int k = 0; k != iv.Length; k++) + { + iv[k] ^= pt[k]; + } + Array.Copy(ct, 0, pt, 0, 16); + + c.Init(true, new KeyParameter(key)); + + c.ProcessBlock(iv, 0, ct, 0); + + Array.Copy(ct, 0, iv, 0, 16); + } + + if (!Arrays.AreEqual(expected, ct)) + { + Fail("CBC monte test failed"); + } + } + + public override string Name + { + get { return "Tnepres"; } + } + + public static void Main(string[] args) + { + RunTest(new TnepresTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/test/BlockCipherTest.cs b/crypto/test/src/test/BlockCipherTest.cs index fc3a99f4e..9a7c6a944 100644 --- a/crypto/test/src/test/BlockCipherTest.cs +++ b/crypto/test/src/test/BlockCipherTest.cs @@ -114,6 +114,8 @@ namespace Org.BouncyCastle.Tests "Rijndael/CBC/PKCS7Padding", "cf87f4d8bb9d1abb36cdd9f44ead7d046db2f802d99e1ef0a5940f306079e08389a44c4a8cc1a47cbaee1128da55bbb7", "Serpent/CBC/PKCS7Padding", + "d8b971931de211cb2d31721773a5b1f9dc4e263efe0465f97c024daa26dd7d03473e9beb82ba809cf36071d4807e4706", + "Tnepres/CBC/PKCS7Padding", "f8940ca31aba8ce1e0693b1ae0b1e08daef6de03c80f019774280052f824ac44540bb8dd74dfad47f83f9c7ec268ca68", "CAST5/CBC/PKCS7Padding", "87b6dc0c5a1d23d42fa740b0548be0b298112000544610d889d6361994cf8e670a19d6af72d7289f", @@ -138,6 +140,8 @@ namespace Org.BouncyCastle.Tests "Rijndael/CTS/NoPadding", "6db2f802d99e1ef0a5940f306079e083cf87f4d8bb9d1abb36cdd9f44ead7d04", "Serpent/CTS/NoPadding", + "dc4e263efe0465f97c024daa26dd7d03d8b971931de211cb2d31721773a5b1f9", + "Tnepres/CTS/NoPadding", "aef6de03c80f019774280052f824ac44f8940ca31aba8ce1e0693b1ae0b1e08d", "CAST5/CTS/NoPadding", "87b6dc0c5a1d23d42fa740b0548be0b289d6361994cf8e6798112000544610d8", @@ -166,6 +170,8 @@ namespace Org.BouncyCastle.Tests "Rijndael/CBC/WithCTS", "6db2f802d99e1ef0a5940f306079e083cf87f4d8bb9d1abb36cdd9f44ead7d04", "Serpent/CBC/WithCTS", + "dc4e263efe0465f97c024daa26dd7d03d8b971931de211cb2d31721773a5b1f9", + "Tnepres/CBC/WithCTS", "aef6de03c80f019774280052f824ac44f8940ca31aba8ce1e0693b1ae0b1e08d", "CAST5/CBC/WithCTS", "87b6dc0c5a1d23d42fa740b0548be0b289d6361994cf8e6798112000544610d8", @@ -251,7 +257,111 @@ namespace Org.BouncyCastle.Tests "Twofish/ECB/TBCPadding", "70336d9c9718a8a2ced1b19deed973a3c58af7ea71a69e7efc4df082dca581c019d7daa58d02b89aab6e8c0d17202439", "RC2/ECB/TBCPadding", - "eb5b889bbcced12eb6b1a3da6a3d965bba66a5edfdd4c8a6b6b1a3da6a3d965b6b5359ba5e69b179" + "eb5b889bbcced12eb6b1a3da6a3d965bba66a5edfdd4c8a6b6b1a3da6a3d965b6b5359ba5e69b179", + "DES/CTR/NoPadding", + "537572e480c1714fb47081d35eb18eaca9e0a5aee982f105438a0db6cece1f6d", + "DESede/CTR/NoPadding", + "481e9872acea7fcfa93b7d4e34ec7bab340c10faba2e43b879d40d38e07c422d", + "SKIPJACK/CTR/NoPadding", + "71143a124e3a0cdeee98a7b843baa05bd1d59faee8ec9b89880e070314a04cc2", + "Blowfish/CTR/NoPadding", + "6cd6f7c5d2c65555d2b31f8614f54ec654f5e7888d515008d59302c3edfcc6cb", + "Twofish/CTR/NoPadding", + "821c54b1b54ae113cf74595eefe10c83d09e95d4599190b9bbd5bc71dd703730", + //"Threefish-256/CTR/NoPadding", + //"546ea995dd302f1efcb1f27d14bad468280a3a7994c2af75dfdf1e9fc5ef2373", + //"Threefish-512/CTR/NoPadding", + //"152df966484ecc2e9ddfc386559732f7f632e4008920804a1bde4efcf2e6e2f2", + //"Threefish-1024/CTR/NoPadding", + //"03953ac751a7377812c6e3e4d14b36c6953f9b390acaa892811c10001c9be454", + "RC2/CTR/NoPadding", + "0a07cb78537cb04c8c5a0a39a15977a7eb19f3c48a42759c234868c391a99c63", + "RC5/CTR/NoPadding", + "c62b233df296283b97f17364d5f69a1ff91f46659cf9856caefd322a936203a7", + "IDEA/CTR/NoPadding", + "dd447da3cbdcf81f4694ab7715d79e3f90af5682e8c318b8f7dadbed6b5c9714", + "Blowfish/EAX/NoPadding", + "bee85ae6512b8a2346d46f7bac31526238091ccc5de75760c9a39628fb45d44a653bfac0", + "CAST5/EAX/NoPadding", + "85e0dbd3402f2179f96d231315ec73f04f64f1b7ab1347423b9aec51a07a7222e2bc65a3", + "DES/EAX/NoPadding", + "07d12249945e77607086f7463f316966466e6a0c0789b3307b8b51a7cc807e3c1fb91f98", + "DESede/EAX/NoPadding", + "278b28f13537dc13bb688c95391754bd6d39c79a7361b407f8dee0b111b264f20391cb0e", + "GOST28147/EAX/NoPadding", + "1416713d52affb595b880be996e838edd377e67dfe822fbb0ff235f1b706e6ce34d68dc5", + "IDEA/EAX/NoPadding", + "b2e9f3e40954c140ac60423466dee0138f84e879fbde003780202bd83c91571b64df7bb7", + "RC2/EAX/NoPadding", + "5d1c095de75bd5eef6a5146f7d6c44545807a8b452f7a38e2719a14f1a269709d2eda2d3", + "SEED/EAX/NoPadding", + "6780f18b2dd1f75a934b5a3e45e8fd44877fd3498a9b919b417b3d8a7c67c6021d74bbaef71841ef", + "Serpent/EAX/NoPadding", + "13c2b1fec2bda74f5ccc8ca31b36a2e91ee024a215387219808640b2fc7a6a41e017aacee3ed893a", + "Tnepres/EAX/NoPadding", + "8d5ac312ca0d436a0154d56568d39811ccf6bb970012398014fc8a49ed669b117443c0249b07ead8", + //"SM4/EAX/NoPadding", + //"e072a95da8e529b41199859482142b3fdfa6b7af27348e5ebf35445a099583dae882affde90ea4a4", + "Twofish/EAX/NoPadding", + "9a90dffe1233a04733fc8869e8ec4cba2fa53d9543f0206825293b1ff102e63f81a60b12204e1fd8", + "IDEA/OFB/NoPadding", + "dd447da3cbdcf81f4053fb446596261cb00a3c49a66085485af5f7c10ba20dad", + "RC2/OFB/NoPadding", + "0a07cb78537cb04c0c74e28a7b86b80f80acadf87d6ef32792f1a8cf74b39f74", + "SEED/OFB/NoPadding", + "9fd249435dc66d3d5d41abad270df5e3c6b972692fadfcb6c311b047f96fb114", + "SEED/OCB/NoPadding", + "eb04b3612769e1ad681f975af1a6f401d94dc88276dd50fc3ebce791c28825c652b7351acbad8c63d4d66191de94c970", + "SEED/CCM/NoPadding", + "8bb16b37e7f1d4eb97bb1fa3b9bfd411aca64a3581bb3c5b2a91346983aa334984d73ad629a847f7", + "SEED/GCM/NoPadding", + "ed5f6293c9a4f280af6695750bfb3bb3b60c214565a049494df955152757812ebfb93705895606c4378498a93f2541b5", + //"SM4/GCM/NoPadding", + //"323b601a951da693f87e53c6832380719b4d4bd306c94248202b7e337c81e2d9de0044b77a4c556f15f6fd19f828236b", + "DES/ECB/TBCPadding", + "466da00648ef0e1f9617b1f002e225251a3248d09172f46b9617b1f002e22525698575eb3998481b", + "GOST28147/ECB/TBCPadding", + "0a77f4114451b37d44c5192619b723dd49093d1047c2373544c5192619b723dde7b0810d205c07ab", + "IDEA/ECB/TBCPadding", + "8c9fd56823ffdc523f6ccf7f614aa6173553e594fc7a21b53f6ccf7f614aa61747a7c95a57b9eaf4", + "RC2/ECB/TBCPadding", + "eb5b889bbcced12eb6b1a3da6a3d965bba66a5edfdd4c8a6b6b1a3da6a3d965b6b5359ba5e69b179", + "SEED/ECB/TBCPadding", + "d53d4ce1f48b9879420949467bfcbfbe2c6a7d4a8770bee0c71211def898d7c509f6e111845db39b4cce1dd155aa592b", + "DES/CBC/TBCPadding", + "60fa2f8fae5aa2a38e9ac77d0246726beb7511e4515feb12cf99f75cc6e0122ad3b3f002c927f1fd", + "GOST28147/CBC/TBCPadding", + "ba87be9c465cbb30e1bf0148daa9639c2e4cbc1b6777cfcda860760686596159aa564fd65e66c125", + "IDEA/CBC/TBCPadding", + "30cd990ebdae80fe12b6c6e4fcd1c064a27d985c276b3d7097351c8684e4c4d922f14e12faecaa0b", + "RC2/CBC/TBCPadding", + "a51facdb3933c9676795cd38cc3146fd4694722b468b1a979a399c77606abf9997b47d2f64a37e2f", + "SEED/CBC/TBCPadding", + "fc34f03ddf4d2a4d9934addc82011af1d5f76ee015b691a6524d7ad5464422d7989825d19e23a60ba759407e13d1ea02", + "DES/CFB8/NoPadding", + "53cb0cdff712a825eb283b23c31e7323aa12495e7e751428b5c4eb89b28a25d4", + "GOST28147/CFB8/NoPadding", + "29f6ca1ca7ae9670413183932a28cdd4a09f2ba630c3c3fbf6f071d3774d7577", + "IDEA/CFB8/NoPadding", + "dd7839d2525420d10f95eec23dbaf3463302c445972a28c563c2635191bc19af", + "RC2/CFB8/NoPadding", + "0aa227f94be3a32ff927c5d25647ea41d7c2a1e94012fc7f2ad6767b9664bce5", + "SEED/CFB8/NoPadding", + "9f1622c3785a034ee4c595df05fb11e69e4d52036e238d2d451e190e87ee876e", + "DES/CTS/NoPadding", + "60fa2f8fae5aa2a38e9ac77d0246726bcf99f75cc6e0122aeb7511e4515feb12", + "GOST28147/CTS/NoPadding", + "ba87be9c465cbb30e1bf0148daa9639ca8607606865961592e4cbc1b6777cfcd", + "IDEA/CTS/NoPadding", + "30cd990ebdae80fe12b6c6e4fcd1c06497351c8684e4c4d9a27d985c276b3d70", + "RC2/CTS/NoPadding", + "a51facdb3933c9676795cd38cc3146fd9a399c77606abf994694722b468b1a97", + "SEED/CTS/NoPadding", + "d5f76ee015b691a6524d7ad5464422d7fc34f03ddf4d2a4d9934addc82011af1", + //"SHACAL-2/CBC/PKCS7Padding", + //"3af7c54ea55d2497162ac9c79d9b2f7837898f83aa4b50b7b762979aa8087669b6a81cdec475ed4d2394d7ad771404a52eb52d245a39f0d7d3e8062d3b0f0e54", + //"SHACAL-2/CBC/TBCPadding", + //"3af7c54ea55d2497162ac9c79d9b2f7837898f83aa4b50b7b762979aa80876693f17fbe9a5baa88ed21b2e1a863dc449061f40cafadfc3cf73486208f87b9352", }; private static readonly string[] cipherTests2 = @@ -329,8 +439,12 @@ namespace Org.BouncyCastle.Tests if (!validModes.Contains(baseMode)) throw new Exception("Unhandled mode: " + mode); + if (baseMode == "CCM") + return 13; if (baseMode == "ECB") return 0; + if (baseMode == "OCB") + return 15; string baseAlgorithm = parts[0]; IBufferedCipher baseCipher = CipherUtilities.GetCipher(baseAlgorithm); @@ -437,11 +551,16 @@ namespace Org.BouncyCastle.Tests if (iv != null) { // TODO Examine short IV handling for these FIPS-compliant modes in Java build - if (mode.StartsWith("CFB") + if (mode.StartsWith("CCM") + || mode.StartsWith("CFB") || mode.StartsWith("CTR") + || mode.StartsWith("EAX") + || mode.StartsWith("GCM") || mode.StartsWith("GOFB") + || mode.StartsWith("OCB") || mode.StartsWith("OFB") - || mode.StartsWith("OPENPGPCFB")) + || mode.StartsWith("OPENPGPCFB") + || mode.StartsWith("SIC")) { // These modes automatically pad out the IV if it is short } -- cgit 1.5.1 From de4c05d989ec0e04acd3a84d07d2e79ebb29b3db Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sat, 21 Nov 2015 17:13:41 +0700 Subject: Add Threefish entries to factories to get tests passing --- crypto/src/security/CipherUtilities.cs | 15 +++++++++++++++ crypto/src/security/GeneratorUtilities.cs | 12 +++++++----- crypto/src/security/ParameterUtilities.cs | 3 +++ crypto/test/src/test/BlockCipherTest.cs | 12 ++++++------ 4 files changed, 31 insertions(+), 11 deletions(-) (limited to 'crypto/test/src') diff --git a/crypto/src/security/CipherUtilities.cs b/crypto/src/security/CipherUtilities.cs index e09eff8d6..3217f3183 100644 --- a/crypto/src/security/CipherUtilities.cs +++ b/crypto/src/security/CipherUtilities.cs @@ -54,6 +54,9 @@ namespace Org.BouncyCastle.Security SERPENT, SKIPJACK, TEA, + THREEFISH_256, + THREEFISH_512, + THREEFISH_1024, TNEPRES, TWOFISH, VMPC, @@ -433,6 +436,15 @@ namespace Org.BouncyCastle.Security case CipherAlgorithm.TEA: blockCipher = new TeaEngine(); break; + case CipherAlgorithm.THREEFISH_256: + blockCipher = new ThreefishEngine(ThreefishEngine.BLOCKSIZE_256); + break; + case CipherAlgorithm.THREEFISH_512: + blockCipher = new ThreefishEngine(ThreefishEngine.BLOCKSIZE_512); + break; + case CipherAlgorithm.THREEFISH_1024: + blockCipher = new ThreefishEngine(ThreefishEngine.BLOCKSIZE_1024); + break; case CipherAlgorithm.TNEPRES: blockCipher = new TnepresEngine(); break; @@ -729,6 +741,9 @@ namespace Org.BouncyCastle.Security case CipherAlgorithm.SERPENT: return new SerpentEngine(); case CipherAlgorithm.SKIPJACK: return new SkipjackEngine(); case CipherAlgorithm.TEA: return new TeaEngine(); + case CipherAlgorithm.THREEFISH_256: return new ThreefishEngine(ThreefishEngine.BLOCKSIZE_256); + case CipherAlgorithm.THREEFISH_512: return new ThreefishEngine(ThreefishEngine.BLOCKSIZE_512); + case CipherAlgorithm.THREEFISH_1024: return new ThreefishEngine(ThreefishEngine.BLOCKSIZE_1024); case CipherAlgorithm.TNEPRES: return new TnepresEngine(); case CipherAlgorithm.TWOFISH: return new TwofishEngine(); case CipherAlgorithm.XTEA: return new XteaEngine(); diff --git a/crypto/src/security/GeneratorUtilities.cs b/crypto/src/security/GeneratorUtilities.cs index 2104a67ba..3beebd05b 100644 --- a/crypto/src/security/GeneratorUtilities.cs +++ b/crypto/src/security/GeneratorUtilities.cs @@ -109,6 +109,9 @@ namespace Org.BouncyCastle.Security AddKgAlgorithm("SERPENT"); AddKgAlgorithm("SKIPJACK"); AddKgAlgorithm("TEA"); + AddKgAlgorithm("THREEFISH-256"); + AddKgAlgorithm("THREEFISH-512"); + AddKgAlgorithm("THREEFISH-1024"); AddKgAlgorithm("TNEPRES"); AddKgAlgorithm("TWOFISH"); AddKgAlgorithm("VMPC"); @@ -180,13 +183,12 @@ namespace Org.BouncyCastle.Security AddDefaultKeySizeEntries(160, "HMACRIPEMD160", "HMACSHA1"); AddDefaultKeySizeEntries(192, "AES", "AES192", "CAMELLIA192", "DESEDE3", "HMACTIGER", "RIJNDAEL", "SERPENT", "TNEPRES"); - AddDefaultKeySizeEntries(224, "HMACSHA224"); + AddDefaultKeySizeEntries(224, "HMACSHA224", "HMACSHA512/224"); AddDefaultKeySizeEntries(256, "AES256", "CAMELLIA", "CAMELLIA256", "CAST6", "GOST28147", - "HC256", "HMACSHA256", "RC5-64", "RC6", "TWOFISH"); + "HC256", "HMACSHA256", "HMACSHA512/256", "RC5-64", "RC6", "THREEFISH-256", "TWOFISH"); AddDefaultKeySizeEntries(384, "HMACSHA384"); - AddDefaultKeySizeEntries(512, "HMACSHA512"); - AddDefaultKeySizeEntries(224, "HMACSHA512/224"); - AddDefaultKeySizeEntries(256, "HMACSHA512/256"); + AddDefaultKeySizeEntries(512, "HMACSHA512", "THREEFISH-512"); + AddDefaultKeySizeEntries(1024, "THREEFISH-1024"); } private static void AddDefaultKeySizeEntries(int size, params string[] algorithms) diff --git a/crypto/src/security/ParameterUtilities.cs b/crypto/src/security/ParameterUtilities.cs index 8fc3732f5..c12155878 100644 --- a/crypto/src/security/ParameterUtilities.cs +++ b/crypto/src/security/ParameterUtilities.cs @@ -104,6 +104,9 @@ namespace Org.BouncyCastle.Security AddAlgorithm("SERPENT"); AddAlgorithm("SKIPJACK"); AddAlgorithm("TEA"); + AddAlgorithm("THREEFISH-256"); + AddAlgorithm("THREEFISH-512"); + AddAlgorithm("THREEFISH-1024"); AddAlgorithm("TNEPRES"); AddAlgorithm("TWOFISH"); AddAlgorithm("VMPC"); diff --git a/crypto/test/src/test/BlockCipherTest.cs b/crypto/test/src/test/BlockCipherTest.cs index 9a7c6a944..e6f92b84e 100644 --- a/crypto/test/src/test/BlockCipherTest.cs +++ b/crypto/test/src/test/BlockCipherTest.cs @@ -268,12 +268,12 @@ namespace Org.BouncyCastle.Tests "6cd6f7c5d2c65555d2b31f8614f54ec654f5e7888d515008d59302c3edfcc6cb", "Twofish/CTR/NoPadding", "821c54b1b54ae113cf74595eefe10c83d09e95d4599190b9bbd5bc71dd703730", - //"Threefish-256/CTR/NoPadding", - //"546ea995dd302f1efcb1f27d14bad468280a3a7994c2af75dfdf1e9fc5ef2373", - //"Threefish-512/CTR/NoPadding", - //"152df966484ecc2e9ddfc386559732f7f632e4008920804a1bde4efcf2e6e2f2", - //"Threefish-1024/CTR/NoPadding", - //"03953ac751a7377812c6e3e4d14b36c6953f9b390acaa892811c10001c9be454", + "Threefish-256/CTR/NoPadding", + "546ea995dd302f1efcb1f27d14bad468280a3a7994c2af75dfdf1e9fc5ef2373", + "Threefish-512/CTR/NoPadding", + "152df966484ecc2e9ddfc386559732f7f632e4008920804a1bde4efcf2e6e2f2", + "Threefish-1024/CTR/NoPadding", + "03953ac751a7377812c6e3e4d14b36c6953f9b390acaa892811c10001c9be454", "RC2/CTR/NoPadding", "0a07cb78537cb04c8c5a0a39a15977a7eb19f3c48a42759c234868c391a99c63", "RC5/CTR/NoPadding", -- cgit 1.5.1 From 610322d49c2ab6915d43b6f7be88ddaa5029ce04 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sun, 22 Nov 2015 15:20:06 +0700 Subject: Add NonMemoableDigest and tests --- crypto/crypto.csproj | 10 ++ crypto/src/crypto/digests/NonMemoableDigest.cs | 62 +++++++++++ .../test/src/crypto/test/NonMemoableDigestTest.cs | 119 +++++++++++++++++++++ crypto/test/src/crypto/test/RegressionTest.cs | 1 + 4 files changed, 192 insertions(+) create mode 100644 crypto/src/crypto/digests/NonMemoableDigest.cs create mode 100644 crypto/test/src/crypto/test/NonMemoableDigestTest.cs (limited to 'crypto/test/src') diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index 572a3cce5..e6ab94ee2 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -3323,6 +3323,11 @@ SubType = "Code" BuildAction = "Compile" /> + +