/// <summary> /// Converts the value of the current <see cref="SecureSymmetricKey" /> to its equivalent binary representation. /// </summary> /// <returns> /// A binary representation of the current <see cref="SecureSymmetricKey" />. /// </returns> public SecureBuffer ToBuffer() { var resultBuffer = new SecureBuffer(SerializedLength); try { using (var controlToken = StateControl.Enter()) { using (var plaintextBuffer = new PinnedBuffer(SerializedPlaintextLength, true)) { KeySource.Access(pinnedKeySourceBuffer => { Array.Copy(pinnedKeySourceBuffer, 0, plaintextBuffer, KeySourceBufferIndex, KeySourceLengthInBytes); }); plaintextBuffer[AlgorithmBufferIndex] = (Byte)Algorithm; plaintextBuffer[DerivationModeBufferIndex] = (Byte)DerivationMode; using (var cipher = BufferEncryptionAlgorithm.ToCipher(RandomnessProvider)) { using (var initializationVector = new PinnedBuffer(cipher.BlockSizeInBytes, true)) { RandomnessProvider.GetBytes(initializationVector); resultBuffer.Access(pinnedResultBuffer => { using (var ciphertext = cipher.Encrypt(plaintextBuffer, BufferEncryptionKey, initializationVector)) { Array.Copy(ciphertext, 0, pinnedResultBuffer, 0, SerializedLength); } }); } } } } return(resultBuffer); } catch { resultBuffer.Dispose(); throw new SecurityException("Key serialization failed."); } }
private Rfc2898DeriveBytes InitializePbkdf2Algorithm() { Rfc2898DeriveBytes result = null; KeySource.Access(buffer => { var iterationSumBuffer = buffer.Take(Pbkdf2IterationSumLengthInBytes); var saltBuffer = buffer.Skip(Pbkdf2IterationSumLengthInBytes).Take(Pbkdf2SaltLengthInBytes); var passwordBuffer = buffer.Skip(Pbkdf2IterationSumLengthInBytes + Pbkdf2SaltLengthInBytes).Take(Pbkdf2PasswordLengthInBytes); var iterationCount = Pbkdf2MinimumIterationCount; foreach (var iterationSumValue in iterationSumBuffer) { iterationCount += iterationSumValue; } result = new Rfc2898DeriveBytes(passwordBuffer.ToArray(), saltBuffer.ToArray(), iterationCount); }); return(result); }
internal PinnedBuffer DeriveKey() { var result = (PinnedBuffer)null; try { using (var controlToken = StateControl.Enter()) { if (DerivationMode == SecureSymmetricKeyDerivationMode.Pbkdf2) { try { // Perform PBKDF2 key-derivation. result = new PinnedBuffer(Pbkdf2Provider.GetBytes(DerivedKeyLength), true); } finally { Pbkdf2Provider.Reset(); } return(result); } result = new PinnedBuffer(DerivedKeyLength, true); using (var sourceWords = new PinnedStructureArray <UInt32>(KeySourceWordCount, true)) { KeySource.Access((PinnedBuffer buffer) => { // Convert the source buffer to an array of 32-bit words. Buffer.BlockCopy(buffer, 0, sourceWords, 0, KeySourceLengthInBytes); }); using (var transformedWords = new PinnedStructureArray <UInt32>(BlockWordCount, true)) { // Copy out the first block. If nothing further is done, this satisfies truncation mode. Array.Copy(sourceWords, transformedWords, BlockWordCount); switch (DerivationMode) { case SecureSymmetricKeyDerivationMode.Truncation: break; case SecureSymmetricKeyDerivationMode.XorLayering: for (var i = 1; i < BlockCount; i++) { for (var j = 0; j < BlockWordCount; j++) { // Perform the XOR layering operation. transformedWords[j] = (transformedWords[j] ^ sourceWords[(i * BlockWordCount) + j]); } } break; case SecureSymmetricKeyDerivationMode.XorLayeringWithSubstitution: for (var i = 1; i < BlockCount; i++) { for (var j = 0; j < BlockWordCount; j++) { // Perform the XOR layering operation with substitution. transformedWords[j] = (SubstituteWord(transformedWords[j]) ^ sourceWords[(i * BlockWordCount) + j]); } } break; default: throw new InvalidOperationException($"The specified key derivation mode, {DerivationMode}, is not supported."); } // Copy out the key bits. Buffer.BlockCopy(transformedWords, 0, result, 0, DerivedKeyLength); } } return(result); } } catch { result?.Dispose(); throw new SecurityException("Key derivation failed."); } }