/* * Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. This file is distributed * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing * permissions and limitations under the License. */ using System; using System.Collections.Generic; using System.Numerics; using System.Security.Cryptography; using System.Text; namespace Amazon.Extensions.CognitoAuthentication.Util { /// /// Class that helps with device SRP authentication /// internal static class CognitoDeviceHelper { public static byte[] Salt { get; set; } public static BigInteger Verifier { get; set; } /// /// Generates the salt, verifier, and secret verification parameters for device SRP /// /// The device key for the associated CognitoDevice /// The device group key for the associated CognitoDevice /// Returns a dictionary with key-value pairings for the salt, verifier, and secret for /// the associated CognitoDevice public static IDictionary GenerateVerificationParameters(string deviceKey, string deviceGroup) { string deviceSecret = GenerateRandomString(); GenerateDeviceSaltAndVerifier(deviceGroup, deviceKey, deviceSecret); byte[] srpVerifier = Verifier.ToByteArray(); Dictionary verificationParams = new Dictionary() { { "salt", Convert.ToBase64String(Salt) }, { "verifier", Convert.ToBase64String(srpVerifier) }, { "secret", deviceSecret } }; return verificationParams; } /// /// Generates the device salt and verifier values and stores them in the appropriate /// CognitoDeviceHelper properties /// /// The device group key for the associated CognitoDevice /// The device key for the CognitoDevice /// The password for the CognitoUser associated with the device public static void GenerateDeviceSaltAndVerifier(string deviceGroupKey, string deviceKey, string password) { byte[] deviceKeyHash = GetDeviceKeyHash(deviceGroupKey, deviceKey, password); Salt = new byte[16]; using (var cryptoRandom = RandomNumberGenerator.Create()) { cryptoRandom.GetBytes(Salt); } Verifier = CalculateVerifier(Salt, deviceKeyHash); } /// /// Calculates the device verifier for the device given the salt and device key hash /// /// The salt for the SHA256 hash to compute the device verifier /// The device key hash for the associated CognitoDevice /// Returns the device verifier for the associated CognitoDevice public static BigInteger CalculateVerifier(byte[] salt, byte[] deviceKeyHash) { byte[] contentBytes = CognitoAuthHelper.CombineBytes(salt, deviceKeyHash); byte[] digest = CognitoAuthHelper.Sha256.ComputeHash(contentBytes); BigInteger x = new BigInteger(digest); return BigInteger.ModPow(x, AuthenticationHelper.g, AuthenticationHelper.N); } /// /// Computes the device key hash given the device group key, device key, and user password /// /// The device group key for the CognitoDevice /// The device key for the CognitoDevice /// The password for the CognitoUser associated with the device /// Returns the device key hash for the given device public static byte[] GetDeviceKeyHash(string deviceGroupKey, string deviceKey, string password) { byte[] contentBytes = CognitoAuthHelper.CombineBytes(Encoding.UTF8.GetBytes(deviceGroupKey), Encoding.UTF8.GetBytes(deviceKey), Encoding.UTF8.GetBytes(":"), Encoding.UTF8.GetBytes(password)); return CognitoAuthHelper.Sha256.ComputeHash(contentBytes); } /// /// Generates a random string using a globally unique identifier /// /// Returns a random string public static string GenerateRandomString() { return Guid.NewGuid().ToString(); } } }