byte[] ComputeAESWithRounds(AESDir aesDir, IV16 iv, byte[] dataBytes, byte[] keyBytes, byte roundsExp, IVCache ivCache, LongRunningOperationContext context) { Guard.NotNull(new object[] { aesDir, iv, dataBytes, keyBytes, roundsExp, ivCache, context }); var rounds = 1u << roundsExp; var roundsToGo = rounds; byte[] inputData = dataBytes; byte[] aesResult = null; while (roundsToGo > 0) { byte[] currentIV = aesDir == AESDir.Encrypt ? ivCache.IVTable.Item2[roundsToGo - 1] : ivCache.IVTable.Item2[ivCache.IVTable.Item2.Length - roundsToGo]; aesResult = this._platform.ComputeAESRound(aesDir, currentIV, inputData, keyBytes); inputData = aesResult; roundsToGo--; // decrement before calculating the percentage or we'll be stuck at 99% // START encryptionProgress / Cancellation context.CancellationToken.ThrowIfCancellationRequested(); decimal progressValue = (rounds - roundsToGo) / (decimal)(rounds); context.EncryptionProgress.Percent = (int)(progressValue * 100m); context.EncryptionProgress.Report(context.EncryptionProgress); // END encryptionProgress } return(aesResult); }
InputDerivedKey32 CreateDerivedKeyWithSHA256(IV16 iv, KeyMaterial64 keyMaterial64) { var keyMaterial = ByteArrays.Concatenate(iv.GetBytes(), keyMaterial64.GetBytes()); var derivedKey = this._platform.ComputeSHA256(keyMaterial); return(new InputDerivedKey32(derivedKey)); }
InputDerivedKey32 CreatePasswordDerivedKeyWithBCrypt(IV16 iv, KeyMaterial64 keyMaterial64, RoundsExponent roundsExponent, LongRunningOperationContext context) { var leftSHA512 = new byte[32]; var rightSHA512 = new byte[32]; Buffer.BlockCopy(keyMaterial64.GetBytes(), 0, leftSHA512, 0, 32); Buffer.BlockCopy(keyMaterial64.GetBytes(), 32, rightSHA512, 0, 32); context.EncryptionProgress.Message = LocalizableStrings.MsgProcessingKey; // Compute the left side on a ThreadPool thread var task = Task.Run(() => BCrypt.CreateHash(iv, leftSHA512, roundsExponent.Value, context)); // Compute the right side after dispatching the work for the right side BCrypt24 rightBCrypt = BCrypt.CreateHash(iv, rightSHA512, roundsExponent.Value, context); // Wait for the left side result task.Wait(context.CancellationToken); // Use the results var combinedHashes = ByteArrays.Concatenate(keyMaterial64.GetBytes(), task.Result.GetBytes(), rightBCrypt.GetBytes()); Debug.Assert(combinedHashes.Length == 64 + 24 + 24); var condensedHash = this._platform.ComputeSHA256(combinedHashes); return(new InputDerivedKey32(condensedHash)); }
/// <summary>'Hash a password using the OpenBSD bcrypt scheme'. Adapted for XDSSec.</summary> /// <exception cref="ArgumentException">Thrown when one or more arguments have unsupported or /// illegal values.</exception> /// <param name="data">The data to hash.</param> /// <param name="iv16">The salt to hash with.</param> /// <param name="logRounds">Between [4..31].</param> /// <param name="context">Object for encryptionProgress indicator and cancelation</param> /// <returns>The hash.</returns> public static BCrypt24 CreateHash(IV16 iv16, byte[] data, byte logRounds, LongRunningOperationContext context) { Guard.NotNull(new object[] { iv16, data, context }); if (logRounds < 4 || logRounds > 31) { throw new ArgumentOutOfRangeException(nameof(logRounds), logRounds, "logRounds must be between 4 and 31 (inclusive)"); } var hash = new BCrypt(context).CryptRaw(data, iv16.GetBytes(), logRounds); return(new BCrypt24(hash)); }
public PaddedData AESDecryptMessage(CipherV2 cipherV2, IV16 iv16, RandomKey32 randomKey, IVCache ivCache, LongRunningOperationContext context) { Guard.NotNull(new object[] { cipherV2, iv16, randomKey, context }); byte[] paddedDataBytes; if (cipherV2.RoundsExponent.Value == RoundsExponent.DontMakeRounds) { paddedDataBytes = this._platform.ComputeAESRound(AESDir.Decrpyt, cipherV2.IV16.GetBytes(), cipherV2.MessageCipher.GetBytes(), randomKey.GetBytes()); } else { context.EncryptionProgress.Message = LocalizableStrings.MsgDecryptingMessage; paddedDataBytes = ComputeAESWithRounds(AESDir.Decrpyt, cipherV2.IV16, cipherV2.MessageCipher.GetBytes(), randomKey.GetBytes(), cipherV2.RoundsExponent.Value, ivCache, context); } return(new PaddedData(paddedDataBytes, cipherV2.PlaintextPadding)); }
/// <summary> /// Purpose: /// </summary> /// <param name="iv"></param> /// <param name="roundsExp"></param> /// <returns></returns> public IVCache CreateIVTable(IV16 iv, byte roundsExp) { Guard.NotNull(new object[] { iv }); var ivCache = new IVCache(); var rounds = 1u << roundsExp; var ivRounds = rounds; var ivTable = new byte[rounds][]; byte[] ivInput = iv.GetBytes(); while (ivRounds > 0) { ivTable[ivTable.Length - ivRounds] = ivInput; ivInput = this._platform.ComputeSHA256(ivInput).Take(16).ToArray(); ivRounds = ivRounds - 1; } ivCache.IVTable = new Tuple <byte[], byte[][]>(iv.GetBytes(), ivTable); return(ivCache); }
CipherV2 EncryptCommon(KeyMaterial64 keyMaterial64, RoundsExponent roundsExponent, LongRunningOperationContext context, Compressed compressed) { if (context == null) { context = new LongRunningOperation(progress => { }, () => { }).Context; } if (this._log) { Debug.WriteLine("KeyMaterial64:"); Debug.WriteLine(keyMaterial64.GetBytes().ToHexView(false)); } if (this._log) { Debug.WriteLine("Compressed:"); Debug.WriteLine(compressed.GetBytes().ToHexView(false)); } PaddedData paddedData = this._internal.ApplyRandomPadding(compressed); if (this._log) { Debug.WriteLine("PaddedData:"); Debug.WriteLine(paddedData.GetBytes().ToHexView(false)); Debug.WriteLine("PlainTextPadding:"); Debug.WriteLine(paddedData.PlaintextPadding); } IV16 iv = new IV16(this._platform.GenerateRandomBytes(16)); if (this._log) { Debug.WriteLine("IV16:"); Debug.WriteLine(iv.GetBytes().ToHexView(false)); } InputDerivedKey32 inputDerivedKey = roundsExponent.Value == RoundsExponent.DontMakeRounds ? CreateDerivedKeyWithSHA256(iv, keyMaterial64) : CreatePasswordDerivedKeyWithBCrypt(iv, keyMaterial64, roundsExponent, context); if (this._log) { Debug.WriteLine("InputDerivedKey32:"); Debug.WriteLine(inputDerivedKey.GetBytes().ToHexView(false)); } RandomKey32 randomKey = new RandomKey32(this._platform.GenerateRandomBytes(32)); if (this._log) { Debug.WriteLine("RandomKey32:"); Debug.WriteLine(randomKey.GetBytes().ToHexView(false)); } XDSSecAPIInternal.IVCache ivCache = roundsExponent.Value == RoundsExponent.DontMakeRounds ? null : this._internal.CreateIVTable(iv, roundsExponent.Value); var cipherV2 = new CipherV2 { RoundsExponent = roundsExponent, IV16 = iv }; this._internal.AESEncryptRandomKeyWithInputDerivedKey(inputDerivedKey, randomKey, cipherV2, ivCache, context); if (this._log) { Debug.WriteLine("RandomKeyCipher32:"); Debug.WriteLine(cipherV2.RandomKeyCipher32.GetBytes().ToHexView(false)); } this._internal.AESEncryptMessageWithRandomKey(paddedData, randomKey, cipherV2, ivCache, context); if (this._log) { Debug.WriteLine("MessageCipher:"); Debug.WriteLine(cipherV2.MessageCipher.GetBytes().ToHexView(false)); } MAC16 mac = CreateMAC(cipherV2, context); if (this._log) { Debug.WriteLine("MAC16:"); Debug.WriteLine(mac.GetBytes().ToHexView(false)); } this._internal.AESEncryptMACWithRandomKey(cipherV2, mac, randomKey, ivCache, context); if (this._log) { Debug.WriteLine("MACCipher16:"); Debug.WriteLine(cipherV2.MACCipher16.GetBytes().ToHexView(false)); } return(cipherV2); }