From ae6698a92434ea94c1dca8300e685cadb99a6a11 Mon Sep 17 00:00:00 2001 From: Suhas Joshi Date: Mon, 8 Dec 2014 15:24:14 -0800 Subject: [PATCH 01/10] Updating to dev NuGet.config --- NuGet.Config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NuGet.Config b/NuGet.Config index 2d3b0cb857..f41e9c631d 100644 --- a/NuGet.Config +++ b/NuGet.Config @@ -1,7 +1,7 @@  - + From 8136affef9c14c3861decc914c164238986e4de9 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 16 Dec 2014 10:21:48 -0800 Subject: [PATCH 02/10] Updating exception filters to use when instead of if --- .../BlobStorageXmlRepository.cs | 2 +- .../Cng/CngAuthenticatedEncryptorBase.cs | 4 ++-- .../DataProtectionExtensions.cs | 4 ++-- .../Dpapi/DpapiDataProtector.cs | 4 ++-- .../KeyManagement/KeyRingBasedDataProtector.cs | 4 ++-- .../Managed/ManagedAuthenticatedEncryptor.cs | 4 ++-- .../TimeLimitedDataProtector.cs | 2 +- src/Microsoft.AspNet.Security.DataProtection/project.json | 1 + 8 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/Microsoft.AspNet.Security.DataProtection.Azure/BlobStorageXmlRepository.cs b/src/Microsoft.AspNet.Security.DataProtection.Azure/BlobStorageXmlRepository.cs index 952b8ce28f..8e728836da 100644 --- a/src/Microsoft.AspNet.Security.DataProtection.Azure/BlobStorageXmlRepository.cs +++ b/src/Microsoft.AspNet.Security.DataProtection.Azure/BlobStorageXmlRepository.cs @@ -61,7 +61,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Azure { blobRef.DownloadToStream(memoryStream); } - catch (StorageException ex) if (ex.RequestInformation.HttpStatusCode == (int)HttpStatusCode.NotFound) + catch (StorageException ex) when (ex.RequestInformation.HttpStatusCode == (int)HttpStatusCode.NotFound) { // 404s are not a fatal error - empty keyring return null; diff --git a/src/Microsoft.AspNet.Security.DataProtection/Cng/CngAuthenticatedEncryptorBase.cs b/src/Microsoft.AspNet.Security.DataProtection/Cng/CngAuthenticatedEncryptorBase.cs index 2e00fb1cb3..37450636a3 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/Cng/CngAuthenticatedEncryptorBase.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/Cng/CngAuthenticatedEncryptorBase.cs @@ -30,7 +30,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Cng pbAdditionalAuthenticatedData: (pbAdditionalAuthenticatedDataArray != null) ? &pbAdditionalAuthenticatedDataArray[additionalAuthenticatedData.Offset] : &dummy, cbAdditionalAuthenticatedData: (uint)additionalAuthenticatedData.Count); } - catch (Exception ex) if (!(ex is CryptographicException)) + catch (Exception ex) when (!(ex is CryptographicException)) { // Homogenize to CryptographicException. throw Error.CryptCommon_GenericError(ex); @@ -71,7 +71,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Cng cbPreBuffer: preBufferSize, cbPostBuffer: postBufferSize); } - catch (Exception ex) if (!(ex is CryptographicException)) + catch (Exception ex) when (!(ex is CryptographicException)) { // Homogenize to CryptographicException. throw Error.CryptCommon_GenericError(ex); diff --git a/src/Microsoft.AspNet.Security.DataProtection/DataProtectionExtensions.cs b/src/Microsoft.AspNet.Security.DataProtection/DataProtectionExtensions.cs index f46852c797..dbfd3a1918 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/DataProtectionExtensions.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/DataProtectionExtensions.cs @@ -36,7 +36,7 @@ namespace Microsoft.AspNet.Security.DataProtection byte[] protectedDataAsBytes = protector.Protect(unprotectedDataAsBytes); return WebEncoders.Base64UrlEncode(protectedDataAsBytes); } - catch (Exception ex) if (!(ex is CryptographicException)) + catch (Exception ex) when (!(ex is CryptographicException)) { // Homogenize exceptions to CryptographicException throw Error.CryptCommon_GenericError(ex); @@ -60,7 +60,7 @@ namespace Microsoft.AspNet.Security.DataProtection byte[] unprotectedDataAsBytes = protector.Unprotect(protectedDataAsBytes); return CryptoUtil.SecureUtf8Encoding.GetString(unprotectedDataAsBytes); } - catch (Exception ex) if (!(ex is CryptographicException)) + catch (Exception ex) when (!(ex is CryptographicException)) { // Homogenize exceptions to CryptographicException throw Error.CryptCommon_GenericError(ex); diff --git a/src/Microsoft.AspNet.Security.DataProtection/Dpapi/DpapiDataProtector.cs b/src/Microsoft.AspNet.Security.DataProtection/Dpapi/DpapiDataProtector.cs index 172a1289cc..cf734290cc 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/Dpapi/DpapiDataProtector.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/Dpapi/DpapiDataProtector.cs @@ -43,7 +43,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Dpapi return _shim.Protect(unprotectedData, _combinedPurposes, _scope) ?? CryptoUtil.Fail("Null return value."); } - catch (Exception ex) if (!(ex is CryptographicException)) + catch (Exception ex) when (!(ex is CryptographicException)) { // Homogenize to CryptographicException throw Error.CryptCommon_GenericError(ex); @@ -57,7 +57,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Dpapi return _shim.Unprotect(protectedData, _combinedPurposes, _scope) ?? CryptoUtil.Fail("Null return value."); } - catch (Exception ex) if (!(ex is CryptographicException)) + catch (Exception ex) when (!(ex is CryptographicException)) { // Homogenize to CryptographicException throw Error.CryptCommon_GenericError(ex); diff --git a/src/Microsoft.AspNet.Security.DataProtection/KeyManagement/KeyRingBasedDataProtector.cs b/src/Microsoft.AspNet.Security.DataProtection/KeyManagement/KeyRingBasedDataProtector.cs index cd5a78e5c1..e5891f2d02 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/KeyManagement/KeyRingBasedDataProtector.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/KeyManagement/KeyRingBasedDataProtector.cs @@ -131,7 +131,7 @@ namespace Microsoft.AspNet.Security.DataProtection.KeyManagement postBufferSize: 0); CryptoUtil.Assert(retVal != null && retVal.Length >= sizeof(uint) + sizeof(Guid), "retVal != null && retVal.Length >= sizeof(uint) + sizeof(Guid)"); } - catch (Exception ex) if (!(ex is CryptographicException)) + catch (Exception ex) when (!(ex is CryptographicException)) { // homogenize all errors to CryptographicException throw Error.Common_EncryptionFailed(ex); @@ -247,7 +247,7 @@ namespace Microsoft.AspNet.Security.DataProtection.KeyManagement CryptoUtil.Assert(retVal != null, "retVal != null"); return retVal; } - catch (Exception ex) if (!(ex is CryptographicException)) + catch (Exception ex) when (!(ex is CryptographicException)) { // homogenize all failures to CryptographicException throw Error.DecryptionFailed(ex); diff --git a/src/Microsoft.AspNet.Security.DataProtection/Managed/ManagedAuthenticatedEncryptor.cs b/src/Microsoft.AspNet.Security.DataProtection/Managed/ManagedAuthenticatedEncryptor.cs index 6d43753665..d384a5ff4a 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/Managed/ManagedAuthenticatedEncryptor.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/Managed/ManagedAuthenticatedEncryptor.cs @@ -278,7 +278,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Managed } } } - catch (Exception ex) if (!(ex is CryptographicException)) + catch (Exception ex) when (!(ex is CryptographicException)) { // Homogenize all exceptions to CryptographicException. throw Error.CryptCommon_GenericError(ex); @@ -382,7 +382,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Managed } } } - catch (Exception ex) if (!(ex is CryptographicException)) + catch (Exception ex) when (!(ex is CryptographicException)) { // Homogenize all exceptions to CryptographicException. throw Error.CryptCommon_GenericError(ex); diff --git a/src/Microsoft.AspNet.Security.DataProtection/TimeLimitedDataProtector.cs b/src/Microsoft.AspNet.Security.DataProtection/TimeLimitedDataProtector.cs index 2bcf57dadd..09bab47aa8 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/TimeLimitedDataProtector.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/TimeLimitedDataProtector.cs @@ -86,7 +86,7 @@ namespace Microsoft.AspNet.Security.DataProtection expiration = new DateTimeOffset((long)utcTicksExpiration, TimeSpan.Zero); return retVal; } - catch (Exception ex) if (!(ex is CryptographicException)) + catch (Exception ex) when (!(ex is CryptographicException)) { // Homogenize all failures to CryptographicException throw Error.CryptCommon_GenericError(ex); diff --git a/src/Microsoft.AspNet.Security.DataProtection/project.json b/src/Microsoft.AspNet.Security.DataProtection/project.json index 8d8bcd50a1..13c7159bec 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/project.json +++ b/src/Microsoft.AspNet.Security.DataProtection/project.json @@ -23,6 +23,7 @@ "aspnetcore50": { "dependencies": { "Microsoft.Win32.Registry": "4.0.0-beta-*", + "System.IO": "4.0.10-beta-*", "System.Security.Cryptography.X509Certificates": "4.0.0-beta-*", "System.Security.Cryptography.Encryption.Aes": "4.0.0-beta-*", "System.Security.Cryptography.Hashing.Algorithms": "4.0.0-beta-*", From 47c870c8718bdca73d3d49212f2d1f1c1e961719 Mon Sep 17 00:00:00 2001 From: Brennan Date: Mon, 15 Dec 2014 15:22:36 -0800 Subject: [PATCH 03/10] Update tests to use official xunit --- .../project.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Microsoft.AspNet.Security.DataProtection.Test/project.json b/test/Microsoft.AspNet.Security.DataProtection.Test/project.json index bad79b6949..af25e55bfe 100644 --- a/test/Microsoft.AspNet.Security.DataProtection.Test/project.json +++ b/test/Microsoft.AspNet.Security.DataProtection.Test/project.json @@ -2,13 +2,13 @@ "dependencies": { "Microsoft.AspNet.Security.DataProtection": "1.0.0-*", "Moq": "4.2.1312.1622", - "Xunit.KRunner": "1.0.0-*" + "xunit.runner.kre": "1.0.0-*" }, "frameworks": { "aspnet50": { } }, "commands": { - "test": "Xunit.KRunner" + "test": "xunit.runner.kre" }, "compilationOptions": { "allowUnsafe": true From e9c4a8c9de1b93e192830a0a0d84730a0395cc7e Mon Sep 17 00:00:00 2001 From: Levi B Date: Thu, 18 Dec 2014 12:05:20 -0800 Subject: [PATCH 04/10] Conditionally run CNG tests only on supported platforms. --- .../Cng/CbcAuthenticatedEncryptorTests.cs | 10 +- .../Cng/CngAuthenticatedEncryptorBaseTests.cs | 10 +- .../Cng/GcmAuthenticatedEncryptorTests.cs | 10 +- ...alRunTestOnlyIfBcryptAvailableAttribute.cs | 58 ++++++++++++ .../PBKDF2/Pbkdf2Tests.cs | 85 +++++++++++++++-- .../SP800_108/SP800_108Tests.cs | 91 ++++++++++++++++++- .../project.json | 1 + 7 files changed, 245 insertions(+), 20 deletions(-) create mode 100644 test/Microsoft.AspNet.Security.DataProtection.Test/ConditionalRunTestOnlyIfBcryptAvailableAttribute.cs diff --git a/test/Microsoft.AspNet.Security.DataProtection.Test/Cng/CbcAuthenticatedEncryptorTests.cs b/test/Microsoft.AspNet.Security.DataProtection.Test/Cng/CbcAuthenticatedEncryptorTests.cs index 7e2027e78a..c7c1acee95 100644 --- a/test/Microsoft.AspNet.Security.DataProtection.Test/Cng/CbcAuthenticatedEncryptorTests.cs +++ b/test/Microsoft.AspNet.Security.DataProtection.Test/Cng/CbcAuthenticatedEncryptorTests.cs @@ -6,13 +6,15 @@ using System.Linq; using System.Security.Cryptography; using System.Text; using Microsoft.AspNet.Security.DataProtection.Cng; +using Microsoft.AspNet.Testing.xunit; using Xunit; namespace Microsoft.AspNet.Security.DataProtection.Test.Cng { public class CbcAuthenticatedEncryptorTests { - [Fact] + [ConditionalFact] + [ConditionalRunTestOnlyIfBcryptAvailable] public void Encrypt_Decrypt_RoundTrips() { // Arrange @@ -32,7 +34,8 @@ namespace Microsoft.AspNet.Security.DataProtection.Test.Cng Assert.Equal(plaintext, decipheredtext); } - [Fact] + [ConditionalFact] + [ConditionalRunTestOnlyIfBcryptAvailable] public void Encrypt_Decrypt_Tampering_Fails() { // Arrange @@ -78,7 +81,8 @@ namespace Microsoft.AspNet.Security.DataProtection.Test.Cng }); } - [Fact] + [ConditionalFact] + [ConditionalRunTestOnlyIfBcryptAvailable] public void Encrypt_KnownKey() { // Arrange diff --git a/test/Microsoft.AspNet.Security.DataProtection.Test/Cng/CngAuthenticatedEncryptorBaseTests.cs b/test/Microsoft.AspNet.Security.DataProtection.Test/Cng/CngAuthenticatedEncryptorBaseTests.cs index 603186a009..1ccabfc429 100644 --- a/test/Microsoft.AspNet.Security.DataProtection.Test/Cng/CngAuthenticatedEncryptorBaseTests.cs +++ b/test/Microsoft.AspNet.Security.DataProtection.Test/Cng/CngAuthenticatedEncryptorBaseTests.cs @@ -3,6 +3,7 @@ using System; using Microsoft.AspNet.Security.DataProtection.Cng; +using Microsoft.AspNet.Testing.xunit; using Moq; using Xunit; @@ -10,7 +11,8 @@ namespace Microsoft.AspNet.Security.DataProtection.Test.Cng { public unsafe class CngAuthenticatedEncryptorBaseTests { - [Fact] + [ConditionalFact] + [ConditionalRunTestOnlyIfBcryptAvailable] public void Decrypt_ForwardsArraySegment() { // Arrange @@ -35,7 +37,8 @@ namespace Microsoft.AspNet.Security.DataProtection.Test.Cng Assert.Equal(new byte[] { 0x20, 0x21, 0x22 }, retVal); } - [Fact] + [ConditionalFact] + [ConditionalRunTestOnlyIfBcryptAvailable] public void Decrypt_HandlesEmptyAADPointerFixup() { // Arrange @@ -60,7 +63,8 @@ namespace Microsoft.AspNet.Security.DataProtection.Test.Cng Assert.Equal(new byte[] { 0x20, 0x21, 0x22 }, retVal); } - [Fact] + [ConditionalFact] + [ConditionalRunTestOnlyIfBcryptAvailable] public void Decrypt_HandlesEmptyCiphertextPointerFixup() { // Arrange diff --git a/test/Microsoft.AspNet.Security.DataProtection.Test/Cng/GcmAuthenticatedEncryptorTests.cs b/test/Microsoft.AspNet.Security.DataProtection.Test/Cng/GcmAuthenticatedEncryptorTests.cs index b1eae351d7..681de03f38 100644 --- a/test/Microsoft.AspNet.Security.DataProtection.Test/Cng/GcmAuthenticatedEncryptorTests.cs +++ b/test/Microsoft.AspNet.Security.DataProtection.Test/Cng/GcmAuthenticatedEncryptorTests.cs @@ -6,13 +6,15 @@ using System.Linq; using System.Security.Cryptography; using System.Text; using Microsoft.AspNet.Security.DataProtection.Cng; +using Microsoft.AspNet.Testing.xunit; using Xunit; namespace Microsoft.AspNet.Security.DataProtection.Test.Cng { public class GcmAuthenticatedEncryptorTests { - [Fact] + [ConditionalFact] + [ConditionalRunTestOnlyIfBcryptAvailable] public void Encrypt_Decrypt_RoundTrips() { // Arrange @@ -29,7 +31,8 @@ namespace Microsoft.AspNet.Security.DataProtection.Test.Cng Assert.Equal(plaintext, decipheredtext); } - [Fact] + [ConditionalFact] + [ConditionalRunTestOnlyIfBcryptAvailable] public void Encrypt_Decrypt_Tampering_Fails() { // Arrange @@ -72,7 +75,8 @@ namespace Microsoft.AspNet.Security.DataProtection.Test.Cng }); } - [Fact] + [ConditionalFact] + [ConditionalRunTestOnlyIfBcryptAvailable] public void Encrypt_KnownKey() { // Arrange diff --git a/test/Microsoft.AspNet.Security.DataProtection.Test/ConditionalRunTestOnlyIfBcryptAvailableAttribute.cs b/test/Microsoft.AspNet.Security.DataProtection.Test/ConditionalRunTestOnlyIfBcryptAvailableAttribute.cs new file mode 100644 index 0000000000..eb6cc86e0e --- /dev/null +++ b/test/Microsoft.AspNet.Security.DataProtection.Test/ConditionalRunTestOnlyIfBcryptAvailableAttribute.cs @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Globalization; +using Microsoft.AspNet.Security.DataProtection.SafeHandles; +using Microsoft.AspNet.Testing.xunit; + +namespace Microsoft.AspNet.Security.DataProtection.Test +{ + public class ConditionalRunTestOnlyIfBcryptAvailableAttribute : Attribute, ITestCondition + { + private static readonly SafeLibraryHandle _bcryptLibHandle = GetBcryptLibHandle(); + + private readonly string _requiredExportFunction; + + public ConditionalRunTestOnlyIfBcryptAvailableAttribute(string requiredExportFunction = null) + { + _requiredExportFunction = requiredExportFunction; + } + + public bool IsMet + { + get + { + if (_bcryptLibHandle == null) + { + return false; // no bcrypt.dll available + } + + return (_requiredExportFunction == null || _bcryptLibHandle.DoesProcExist(_requiredExportFunction)); + } + } + + public string SkipReason + { + get + { + return (_bcryptLibHandle != null) + ? String.Format(CultureInfo.InvariantCulture, "Export {0} not found in bcrypt.dll", _requiredExportFunction) + : "bcrypt.dll not found on this platform."; + } + } + + private static SafeLibraryHandle GetBcryptLibHandle() + { + try + { + return SafeLibraryHandle.Open("bcrypt.dll"); + } + catch + { + // If we're not on an OS with BCRYPT.DLL, just bail. + return null; + } + } + } +} diff --git a/test/Microsoft.AspNet.Security.DataProtection.Test/PBKDF2/Pbkdf2Tests.cs b/test/Microsoft.AspNet.Security.DataProtection.Test/PBKDF2/Pbkdf2Tests.cs index 501f759a89..6fed8294d7 100644 --- a/test/Microsoft.AspNet.Security.DataProtection.Test/PBKDF2/Pbkdf2Tests.cs +++ b/test/Microsoft.AspNet.Security.DataProtection.Test/PBKDF2/Pbkdf2Tests.cs @@ -4,6 +4,7 @@ using System; using System.Text; using Microsoft.AspNet.Security.DataProtection.PBKDF2; +using Microsoft.AspNet.Testing.xunit; using Xunit; namespace Microsoft.AspNet.Security.DataProtection.Test.PBKDF2 @@ -23,7 +24,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Test.PBKDF2 [InlineData("my-password", KeyDerivationPrf.Sha512, 5, 512 / 8 - 1, "ZTallQJrFn0279xIzaiA1XqatVTGei+ZjKngA7bIMtKMDUw6YJeGUQpFG8iGTgN+ri3LNDktNbzwfcSyZmm9")] [InlineData("my-password", KeyDerivationPrf.Sha512, 5, 512 / 8 + 0, "ZTallQJrFn0279xIzaiA1XqatVTGei+ZjKngA7bIMtKMDUw6YJeGUQpFG8iGTgN+ri3LNDktNbzwfcSyZmm90Q==")] [InlineData("my-password", KeyDerivationPrf.Sha512, 5, 512 / 8 + 1, "ZTallQJrFn0279xIzaiA1XqatVTGei+ZjKngA7bIMtKMDUw6YJeGUQpFG8iGTgN+ri3LNDktNbzwfcSyZmm90Wk=")] - public void RunTest_Normal(string password, KeyDerivationPrf prf, int iterationCount, int numBytesRequested, string expectedValueAsBase64) + public void RunTest_Normal_Managed(string password, KeyDerivationPrf prf, int iterationCount, int numBytesRequested, string expectedValueAsBase64) { // Arrange byte[] salt = new byte[256]; @@ -32,14 +33,86 @@ namespace Microsoft.AspNet.Security.DataProtection.Test.PBKDF2 salt[i] = (byte)i; } - // Act & assert - fully managed, Win7, and Win8 + // Act & assert TestProvider(password, salt, prf, iterationCount, numBytesRequested, expectedValueAsBase64); + } + + // The 'numBytesRequested' parameters below are chosen to exercise code paths where + // this value straddles the digest length of the PRF. We only use 5 iterations so + // that our unit tests are fast. + [ConditionalTheory] + [ConditionalRunTestOnlyIfBcryptAvailable("BCryptDeriveKeyPBKDF2")] + [InlineData("my-password", KeyDerivationPrf.Sha1, 5, 160 / 8 - 1, "efmxNcKD/U1urTEDGvsThlPnHA==")] + [InlineData("my-password", KeyDerivationPrf.Sha1, 5, 160 / 8 + 0, "efmxNcKD/U1urTEDGvsThlPnHDI=")] + [InlineData("my-password", KeyDerivationPrf.Sha1, 5, 160 / 8 + 1, "efmxNcKD/U1urTEDGvsThlPnHDLk")] + [InlineData("my-password", KeyDerivationPrf.Sha256, 5, 256 / 8 - 1, "JRNz8bPKS02EG1vf7eWjA64IeeI+TI8gBEwb1oVvRA==")] + [InlineData("my-password", KeyDerivationPrf.Sha256, 5, 256 / 8 + 0, "JRNz8bPKS02EG1vf7eWjA64IeeI+TI8gBEwb1oVvRLo=")] + [InlineData("my-password", KeyDerivationPrf.Sha256, 5, 256 / 8 + 1, "JRNz8bPKS02EG1vf7eWjA64IeeI+TI8gBEwb1oVvRLpk")] + [InlineData("my-password", KeyDerivationPrf.Sha512, 5, 512 / 8 - 1, "ZTallQJrFn0279xIzaiA1XqatVTGei+ZjKngA7bIMtKMDUw6YJeGUQpFG8iGTgN+ri3LNDktNbzwfcSyZmm9")] + [InlineData("my-password", KeyDerivationPrf.Sha512, 5, 512 / 8 + 0, "ZTallQJrFn0279xIzaiA1XqatVTGei+ZjKngA7bIMtKMDUw6YJeGUQpFG8iGTgN+ri3LNDktNbzwfcSyZmm90Q==")] + [InlineData("my-password", KeyDerivationPrf.Sha512, 5, 512 / 8 + 1, "ZTallQJrFn0279xIzaiA1XqatVTGei+ZjKngA7bIMtKMDUw6YJeGUQpFG8iGTgN+ri3LNDktNbzwfcSyZmm90Wk=")] + public void RunTest_Normal_Win7(string password, KeyDerivationPrf prf, int iterationCount, int numBytesRequested, string expectedValueAsBase64) + { + // Arrange + byte[] salt = new byte[256]; + for (int i = 0; i < salt.Length; i++) + { + salt[i] = (byte)i; + } + + // Act & assert TestProvider(password, salt, prf, iterationCount, numBytesRequested, expectedValueAsBase64); + } + + // The 'numBytesRequested' parameters below are chosen to exercise code paths where + // this value straddles the digest length of the PRF. We only use 5 iterations so + // that our unit tests are fast. + [ConditionalTheory] + [ConditionalRunTestOnlyIfBcryptAvailable("BCryptKeyDerivation")] + [InlineData("my-password", KeyDerivationPrf.Sha1, 5, 160 / 8 - 1, "efmxNcKD/U1urTEDGvsThlPnHA==")] + [InlineData("my-password", KeyDerivationPrf.Sha1, 5, 160 / 8 + 0, "efmxNcKD/U1urTEDGvsThlPnHDI=")] + [InlineData("my-password", KeyDerivationPrf.Sha1, 5, 160 / 8 + 1, "efmxNcKD/U1urTEDGvsThlPnHDLk")] + [InlineData("my-password", KeyDerivationPrf.Sha256, 5, 256 / 8 - 1, "JRNz8bPKS02EG1vf7eWjA64IeeI+TI8gBEwb1oVvRA==")] + [InlineData("my-password", KeyDerivationPrf.Sha256, 5, 256 / 8 + 0, "JRNz8bPKS02EG1vf7eWjA64IeeI+TI8gBEwb1oVvRLo=")] + [InlineData("my-password", KeyDerivationPrf.Sha256, 5, 256 / 8 + 1, "JRNz8bPKS02EG1vf7eWjA64IeeI+TI8gBEwb1oVvRLpk")] + [InlineData("my-password", KeyDerivationPrf.Sha512, 5, 512 / 8 - 1, "ZTallQJrFn0279xIzaiA1XqatVTGei+ZjKngA7bIMtKMDUw6YJeGUQpFG8iGTgN+ri3LNDktNbzwfcSyZmm9")] + [InlineData("my-password", KeyDerivationPrf.Sha512, 5, 512 / 8 + 0, "ZTallQJrFn0279xIzaiA1XqatVTGei+ZjKngA7bIMtKMDUw6YJeGUQpFG8iGTgN+ri3LNDktNbzwfcSyZmm90Q==")] + [InlineData("my-password", KeyDerivationPrf.Sha512, 5, 512 / 8 + 1, "ZTallQJrFn0279xIzaiA1XqatVTGei+ZjKngA7bIMtKMDUw6YJeGUQpFG8iGTgN+ri3LNDktNbzwfcSyZmm90Wk=")] + public void RunTest_Normal_Win8(string password, KeyDerivationPrf prf, int iterationCount, int numBytesRequested, string expectedValueAsBase64) + { + // Arrange + byte[] salt = new byte[256]; + for (int i = 0; i < salt.Length; i++) + { + salt[i] = (byte)i; + } + + // Act & assert TestProvider(password, salt, prf, iterationCount, numBytesRequested, expectedValueAsBase64); } [Fact] - public void RunTest_WithLongPassword() + public void RunTest_WithLongPassword_Managed() + { + RunTest_WithLongPassword_Impl(); + } + + [ConditionalFact] + [ConditionalRunTestOnlyIfBcryptAvailable("BCryptDeriveKeyPBKDF2")] + public void RunTest_WithLongPassword_Win7() + { + RunTest_WithLongPassword_Impl(); + } + + [ConditionalFact] + [ConditionalRunTestOnlyIfBcryptAvailable("BCryptKeyDerivation")] + public void RunTest_WithLongPassword_Win8() + { + RunTest_WithLongPassword_Impl(); + } + + private static void RunTest_WithLongPassword_Impl() + where TProvider : IPbkdf2Provider, new() { // Arrange string password = new String('x', 50000); // 50,000 char password @@ -49,10 +122,8 @@ namespace Microsoft.AspNet.Security.DataProtection.Test.PBKDF2 const int iterationCount = 5; const int numBytesRequested = 128; - // Act & assert - fully managed, Win7, and Win8 - TestProvider(password, salt, prf, iterationCount, numBytesRequested, expectedDerivedKeyBase64); - TestProvider(password, salt, prf, iterationCount, numBytesRequested, expectedDerivedKeyBase64); - TestProvider(password, salt, prf, iterationCount, numBytesRequested, expectedDerivedKeyBase64); + // Act & assert + TestProvider(password, salt, prf, iterationCount, numBytesRequested, expectedDerivedKeyBase64); } private static void TestProvider(string password, byte[] salt, KeyDerivationPrf prf, int iterationCount, int numBytesRequested, string expectedDerivedKeyAsBase64) diff --git a/test/Microsoft.AspNet.Security.DataProtection.Test/SP800_108/SP800_108Tests.cs b/test/Microsoft.AspNet.Security.DataProtection.Test/SP800_108/SP800_108Tests.cs index 9feb26b816..2705296ed1 100644 --- a/test/Microsoft.AspNet.Security.DataProtection.Test/SP800_108/SP800_108Tests.cs +++ b/test/Microsoft.AspNet.Security.DataProtection.Test/SP800_108/SP800_108Tests.cs @@ -5,6 +5,7 @@ using System; using System.Security.Cryptography; using System.Text; using Microsoft.AspNet.Security.DataProtection.SP800_108; +using Microsoft.AspNet.Testing.xunit; using Xunit; namespace Microsoft.AspNet.Security.DataProtection.Test.SP800_108 @@ -19,7 +20,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Test.SP800_108 [InlineData(512 / 8 - 1, "V47WmHzPSkdC2vkLAomIjCzZlDOAetll3yJLcSvon7LJFjJpEN+KnSNp+gIpeydKMsENkflbrIZ/3s6GkEaH")] [InlineData(512 / 8 + 0, "mVaFM4deXLl610CmnCteNzxgbM/VkmKznAlPauHcDBn0le06uOjAKLHx0LfoU2/Ttq9nd78Y6Nk6wArmdwJgJg==")] [InlineData(512 / 8 + 1, "GaHPeqdUxriFpjRtkYQYWr5/iqneD/+hPhVJQt4rXblxSpB1UUqGqL00DMU/FJkX0iMCfqUjQXtXyfks+p++Ev4=")] - public void DeriveKeyWithContextHeader_Normal(int numDerivedBytes, string expectedDerivedSubkeyAsBase64) + public void DeriveKeyWithContextHeader_Normal_Managed(int numDerivedBytes, string expectedDerivedSubkeyAsBase64) { // Arrange byte[] kdk = Encoding.UTF8.GetBytes("kdk"); @@ -27,9 +28,45 @@ namespace Microsoft.AspNet.Security.DataProtection.Test.SP800_108 byte[] contextHeader = Encoding.UTF8.GetBytes("contextHeader"); byte[] context = Encoding.UTF8.GetBytes("context"); - // Act & assert - managed, Win7, Win8 + // Act & assert TestManagedKeyDerivation(kdk, label, contextHeader, context, numDerivedBytes, expectedDerivedSubkeyAsBase64); + } + + // The 'numBytesRequested' parameters below are chosen to exercise code paths where + // this value straddles the digest length of the PRF (which is hardcoded to HMACSHA512). + [ConditionalTheory] + [ConditionalRunTestOnlyIfBcryptAvailable] + [InlineData(512 / 8 - 1, "V47WmHzPSkdC2vkLAomIjCzZlDOAetll3yJLcSvon7LJFjJpEN+KnSNp+gIpeydKMsENkflbrIZ/3s6GkEaH")] + [InlineData(512 / 8 + 0, "mVaFM4deXLl610CmnCteNzxgbM/VkmKznAlPauHcDBn0le06uOjAKLHx0LfoU2/Ttq9nd78Y6Nk6wArmdwJgJg==")] + [InlineData(512 / 8 + 1, "GaHPeqdUxriFpjRtkYQYWr5/iqneD/+hPhVJQt4rXblxSpB1UUqGqL00DMU/FJkX0iMCfqUjQXtXyfks+p++Ev4=")] + public void DeriveKeyWithContextHeader_Normal_Win7(int numDerivedBytes, string expectedDerivedSubkeyAsBase64) + { + // Arrange + byte[] kdk = Encoding.UTF8.GetBytes("kdk"); + byte[] label = Encoding.UTF8.GetBytes("label"); + byte[] contextHeader = Encoding.UTF8.GetBytes("contextHeader"); + byte[] context = Encoding.UTF8.GetBytes("context"); + + // Act & assert TestCngKeyDerivation((pbKdk, cbKdk) => new Win7SP800_108_CTR_HMACSHA512Provider(pbKdk, cbKdk), kdk, label, contextHeader, context, numDerivedBytes, expectedDerivedSubkeyAsBase64); + } + + // The 'numBytesRequested' parameters below are chosen to exercise code paths where + // this value straddles the digest length of the PRF (which is hardcoded to HMACSHA512). + [ConditionalTheory] + [ConditionalRunTestOnlyIfBcryptAvailable("BCryptKeyDerivation")] + [InlineData(512 / 8 - 1, "V47WmHzPSkdC2vkLAomIjCzZlDOAetll3yJLcSvon7LJFjJpEN+KnSNp+gIpeydKMsENkflbrIZ/3s6GkEaH")] + [InlineData(512 / 8 + 0, "mVaFM4deXLl610CmnCteNzxgbM/VkmKznAlPauHcDBn0le06uOjAKLHx0LfoU2/Ttq9nd78Y6Nk6wArmdwJgJg==")] + [InlineData(512 / 8 + 1, "GaHPeqdUxriFpjRtkYQYWr5/iqneD/+hPhVJQt4rXblxSpB1UUqGqL00DMU/FJkX0iMCfqUjQXtXyfks+p++Ev4=")] + public void DeriveKeyWithContextHeader_Normal_Win8(int numDerivedBytes, string expectedDerivedSubkeyAsBase64) + { + // Arrange + byte[] kdk = Encoding.UTF8.GetBytes("kdk"); + byte[] label = Encoding.UTF8.GetBytes("label"); + byte[] contextHeader = Encoding.UTF8.GetBytes("contextHeader"); + byte[] context = Encoding.UTF8.GetBytes("context"); + + // Act & assert TestCngKeyDerivation((pbKdk, cbKdk) => new Win8SP800_108_CTR_HMACSHA512Provider(pbKdk, cbKdk), kdk, label, contextHeader, context, numDerivedBytes, expectedDerivedSubkeyAsBase64); } @@ -39,7 +76,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Test.SP800_108 [InlineData(512 / 8 - 1, "rt2hM6kkQ8hAXmkHx0TU4o3Q+S7fie6b3S1LAq107k++P9v8uSYA2G+WX3pJf9ZkpYrTKD7WUIoLkgA1R9lk")] [InlineData(512 / 8 + 0, "RKiXmHSrWq5gkiRSyNZWNJrMR0jDyYHJMt9odOayRAE5wLSX2caINpQmfzTH7voJQi3tbn5MmD//dcspghfBiw==")] [InlineData(512 / 8 + 1, "KedXO0zAIZ3AfnPqY1NnXxpC3HDHIxefG4bwD3g6nWYEc5+q7pjbam71Yqj0zgHMNC9Z7BX3wS1/tajFocRWZUk=")] - public void DeriveKeyWithContextHeader_LongKey(int numDerivedBytes, string expectedDerivedSubkeyAsBase64) + public void DeriveKeyWithContextHeader_LongKey_Managed(int numDerivedBytes, string expectedDerivedSubkeyAsBase64) { // Arrange byte[] kdk = new byte[50000]; // CNG can't normally handle a 50,000 byte KDK, but we coerce it into working :) @@ -52,9 +89,55 @@ namespace Microsoft.AspNet.Security.DataProtection.Test.SP800_108 byte[] contextHeader = Encoding.UTF8.GetBytes("contextHeader"); byte[] context = Encoding.UTF8.GetBytes("context"); - // Act & assert - managed, Win7, Win8 + // Act & assert TestManagedKeyDerivation(kdk, label, contextHeader, context, numDerivedBytes, expectedDerivedSubkeyAsBase64); + } + + // The 'numBytesRequested' parameters below are chosen to exercise code paths where + // this value straddles the digest length of the PRF (which is hardcoded to HMACSHA512). + [ConditionalTheory] + [ConditionalRunTestOnlyIfBcryptAvailable] + [InlineData(512 / 8 - 1, "rt2hM6kkQ8hAXmkHx0TU4o3Q+S7fie6b3S1LAq107k++P9v8uSYA2G+WX3pJf9ZkpYrTKD7WUIoLkgA1R9lk")] + [InlineData(512 / 8 + 0, "RKiXmHSrWq5gkiRSyNZWNJrMR0jDyYHJMt9odOayRAE5wLSX2caINpQmfzTH7voJQi3tbn5MmD//dcspghfBiw==")] + [InlineData(512 / 8 + 1, "KedXO0zAIZ3AfnPqY1NnXxpC3HDHIxefG4bwD3g6nWYEc5+q7pjbam71Yqj0zgHMNC9Z7BX3wS1/tajFocRWZUk=")] + public void DeriveKeyWithContextHeader_LongKey_Win7(int numDerivedBytes, string expectedDerivedSubkeyAsBase64) + { + // Arrange + byte[] kdk = new byte[50000]; // CNG can't normally handle a 50,000 byte KDK, but we coerce it into working :) + for (int i = 0; i < kdk.Length; i++) + { + kdk[i] = (byte)i; + } + + byte[] label = Encoding.UTF8.GetBytes("label"); + byte[] contextHeader = Encoding.UTF8.GetBytes("contextHeader"); + byte[] context = Encoding.UTF8.GetBytes("context"); + + // Act & assert TestCngKeyDerivation((pbKdk, cbKdk) => new Win7SP800_108_CTR_HMACSHA512Provider(pbKdk, cbKdk), kdk, label, contextHeader, context, numDerivedBytes, expectedDerivedSubkeyAsBase64); + } + + // The 'numBytesRequested' parameters below are chosen to exercise code paths where + // this value straddles the digest length of the PRF (which is hardcoded to HMACSHA512). + [ConditionalTheory] + [ConditionalRunTestOnlyIfBcryptAvailable("BCryptKeyDerivation")] + [InlineData(512 / 8 - 1, "rt2hM6kkQ8hAXmkHx0TU4o3Q+S7fie6b3S1LAq107k++P9v8uSYA2G+WX3pJf9ZkpYrTKD7WUIoLkgA1R9lk")] + [InlineData(512 / 8 + 0, "RKiXmHSrWq5gkiRSyNZWNJrMR0jDyYHJMt9odOayRAE5wLSX2caINpQmfzTH7voJQi3tbn5MmD//dcspghfBiw==")] + [InlineData(512 / 8 + 1, "KedXO0zAIZ3AfnPqY1NnXxpC3HDHIxefG4bwD3g6nWYEc5+q7pjbam71Yqj0zgHMNC9Z7BX3wS1/tajFocRWZUk=")] + public void DeriveKeyWithContextHeader_LongKey_Win8(int numDerivedBytes, string expectedDerivedSubkeyAsBase64) + { + // Arrange + byte[] kdk = new byte[50000]; // CNG can't normally handle a 50,000 byte KDK, but we coerce it into working :) + for (int i = 0; i < kdk.Length; i++) + { + kdk[i] = (byte)i; + } + + byte[] label = Encoding.UTF8.GetBytes("label"); + byte[] contextHeader = Encoding.UTF8.GetBytes("contextHeader"); + byte[] context = Encoding.UTF8.GetBytes("context"); + + // Act & assert TestCngKeyDerivation((pbKdk, cbKdk) => new Win8SP800_108_CTR_HMACSHA512Provider(pbKdk, cbKdk), kdk, label, contextHeader, context, numDerivedBytes, expectedDerivedSubkeyAsBase64); } diff --git a/test/Microsoft.AspNet.Security.DataProtection.Test/project.json b/test/Microsoft.AspNet.Security.DataProtection.Test/project.json index af25e55bfe..2ee987c400 100644 --- a/test/Microsoft.AspNet.Security.DataProtection.Test/project.json +++ b/test/Microsoft.AspNet.Security.DataProtection.Test/project.json @@ -1,6 +1,7 @@ { "dependencies": { "Microsoft.AspNet.Security.DataProtection": "1.0.0-*", + "Microsoft.AspNet.Testing": "1.0.0-*", "Moq": "4.2.1312.1622", "xunit.runner.kre": "1.0.0-*" }, From d5143f5004f6ef9e6780b37c368848010d8dce9f Mon Sep 17 00:00:00 2001 From: Aligned Date: Mon, 12 Jan 2015 15:13:17 -0600 Subject: [PATCH 05/10] Change ASP.NET vNext to ASP.Net 5 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a8102a4eb3..8599b75f90 100644 --- a/README.md +++ b/README.md @@ -3,4 +3,4 @@ DataProtection Data Protection APIs -This project is part of ASP.NET vNext. You can find samples, documentation and getting started instructions for ASP.NET vNext at the [Home](https://github.com/aspnet/home) repo. +This project is part of ASP.NET 5. You can find samples, documentation and getting started instructions for ASP.NET 5 at the [Home](https://github.com/aspnet/home) repo. From 1d49807eeee58e4014733803d7c230d0f692fd15 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 20 Jan 2015 01:30:29 -0800 Subject: [PATCH 06/10] Updating build.cmd and build.sh to use dotnetsdk --- build.cmd | 6 +++--- build.sh | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build.cmd b/build.cmd index 86ca5bbbf1..c8041fdd9d 100644 --- a/build.cmd +++ b/build.cmd @@ -20,9 +20,9 @@ IF EXIST packages\KoreBuild goto run .nuget\NuGet.exe install Sake -version 0.2 -o packages -ExcludeVersion IF "%SKIP_KRE_INSTALL%"=="1" goto run -CALL packages\KoreBuild\build\kvm upgrade -runtime CLR -x86 -CALL packages\KoreBuild\build\kvm install default -runtime CoreCLR -x86 +CALL packages\KoreBuild\build\dotnetsdk upgrade -runtime CLR -x86 +CALL packages\KoreBuild\build\dotnetsdk install default -runtime CoreCLR -x86 :run -CALL packages\KoreBuild\build\kvm use default -runtime CLR -x86 +CALL packages\KoreBuild\build\dotnetsdk use default -runtime CLR -x86 packages\Sake\tools\Sake.exe -I packages\KoreBuild\build -f makefile.shade %* diff --git a/build.sh b/build.sh index c7873ef58e..3f3c731c04 100644 --- a/build.sh +++ b/build.sh @@ -28,11 +28,11 @@ if test ! -d packages/KoreBuild; then fi if ! type k > /dev/null 2>&1; then - source packages/KoreBuild/build/kvm.sh + source setup/dotnetsdk.sh fi if ! type k > /dev/null 2>&1; then - kvm upgrade + dotnetsdk upgrade fi mono packages/Sake/tools/Sake.exe -I packages/KoreBuild/build -f makefile.shade "$@" From 962b8f38f85ce1dae54a1e11e3da0c42865cdc26 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 20 Jan 2015 01:35:33 -0800 Subject: [PATCH 07/10] Updating build.cmd and build.sh to use dotnetsdk --- build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sh b/build.sh index 3f3c731c04..350d7e389a 100644 --- a/build.sh +++ b/build.sh @@ -28,7 +28,7 @@ if test ! -d packages/KoreBuild; then fi if ! type k > /dev/null 2>&1; then - source setup/dotnetsdk.sh + source packages/KoreBuild/build/dotnetsdk.sh fi if ! type k > /dev/null 2>&1; then From 04e7bca8bfcac58003f5e770e0687f5d4e573809 Mon Sep 17 00:00:00 2001 From: Levi B Date: Tue, 20 Jan 2015 13:49:29 -0800 Subject: [PATCH 08/10] Normalize .kproj files BOM and line endings --- .../Microsoft.AspNet.Security.DataProtection.Azure.kproj | 2 +- ...Microsoft.AspNet.Security.DataProtection.Compatibility.kproj | 2 +- .../Microsoft.AspNet.Security.DataProtection.kproj | 2 +- .../Microsoft.AspNet.Security.DataProtection.Test.kproj | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.AspNet.Security.DataProtection.Azure/Microsoft.AspNet.Security.DataProtection.Azure.kproj b/src/Microsoft.AspNet.Security.DataProtection.Azure/Microsoft.AspNet.Security.DataProtection.Azure.kproj index 60874ae6e1..0279cb8079 100644 --- a/src/Microsoft.AspNet.Security.DataProtection.Azure/Microsoft.AspNet.Security.DataProtection.Azure.kproj +++ b/src/Microsoft.AspNet.Security.DataProtection.Azure/Microsoft.AspNet.Security.DataProtection.Azure.kproj @@ -1,4 +1,4 @@ - + 14.0 diff --git a/src/Microsoft.AspNet.Security.DataProtection.Compatibility/Microsoft.AspNet.Security.DataProtection.Compatibility.kproj b/src/Microsoft.AspNet.Security.DataProtection.Compatibility/Microsoft.AspNet.Security.DataProtection.Compatibility.kproj index 1be00812a1..24ce7cf3b8 100644 --- a/src/Microsoft.AspNet.Security.DataProtection.Compatibility/Microsoft.AspNet.Security.DataProtection.Compatibility.kproj +++ b/src/Microsoft.AspNet.Security.DataProtection.Compatibility/Microsoft.AspNet.Security.DataProtection.Compatibility.kproj @@ -1,4 +1,4 @@ - + 14.0 diff --git a/src/Microsoft.AspNet.Security.DataProtection/Microsoft.AspNet.Security.DataProtection.kproj b/src/Microsoft.AspNet.Security.DataProtection/Microsoft.AspNet.Security.DataProtection.kproj index 876b528aad..885bbdd20e 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/Microsoft.AspNet.Security.DataProtection.kproj +++ b/src/Microsoft.AspNet.Security.DataProtection/Microsoft.AspNet.Security.DataProtection.kproj @@ -1,4 +1,4 @@ - + 14.0 diff --git a/test/Microsoft.AspNet.Security.DataProtection.Test/Microsoft.AspNet.Security.DataProtection.Test.kproj b/test/Microsoft.AspNet.Security.DataProtection.Test/Microsoft.AspNet.Security.DataProtection.Test.kproj index b92a332f71..66ecc0ff24 100644 --- a/test/Microsoft.AspNet.Security.DataProtection.Test/Microsoft.AspNet.Security.DataProtection.Test.kproj +++ b/test/Microsoft.AspNet.Security.DataProtection.Test/Microsoft.AspNet.Security.DataProtection.Test.kproj @@ -1,4 +1,4 @@ - + 14.0 From 9f0883321064223a67750da8068758b7c5e03c42 Mon Sep 17 00:00:00 2001 From: Wei Wang Date: Tue, 20 Jan 2015 18:12:55 -0800 Subject: [PATCH 09/10] Rename SKIP_KRE_INSTALL to SKIP_DOTNET_INSTALL --- build.cmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.cmd b/build.cmd index c8041fdd9d..220a1ff561 100644 --- a/build.cmd +++ b/build.cmd @@ -19,7 +19,7 @@ IF EXIST packages\KoreBuild goto run .nuget\NuGet.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre .nuget\NuGet.exe install Sake -version 0.2 -o packages -ExcludeVersion -IF "%SKIP_KRE_INSTALL%"=="1" goto run +IF "%SKIP_DOTNET_INSTALL%"=="1" goto run CALL packages\KoreBuild\build\dotnetsdk upgrade -runtime CLR -x86 CALL packages\KoreBuild\build\dotnetsdk install default -runtime CoreCLR -x86 From b5f1eff89e9be8a9b0769f3f6351b2d3fa65a51b Mon Sep 17 00:00:00 2001 From: Suhas Joshi Date: Wed, 21 Jan 2015 15:45:10 -0800 Subject: [PATCH 10/10] Updating to release NuGet.config --- NuGet.Config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NuGet.Config b/NuGet.Config index f41e9c631d..2d3b0cb857 100644 --- a/NuGet.Config +++ b/NuGet.Config @@ -1,7 +1,7 @@  - +