/// <summary> /// Creates a new Secret from another secret object. /// </summary> public Secret(ISecret secret) { if (secret == null) { throw new ArgumentNullException(nameof(secret)); } Secret other = secret as Secret; if (other != null) { // Fast-track: simple deep copy scenario. this._localAllocHandle = other._localAllocHandle.Duplicate(); this._plaintextLength = other._plaintextLength; } else { // Copy the secret to a temporary managed buffer, then protect the buffer. // We pin the temp buffer and zero it out when we're finished to limit exposure of the secret. byte[] tempPlaintextBuffer = new byte[secret.Length]; fixed(byte *pbTempPlaintextBuffer = tempPlaintextBuffer) { try { secret.WriteSecretIntoBuffer(new ArraySegment <byte>(tempPlaintextBuffer)); _localAllocHandle = Protect(pbTempPlaintextBuffer, (uint)tempPlaintextBuffer.Length); _plaintextLength = (uint)tempPlaintextBuffer.Length; } finally { UnsafeBufferUtil.SecureZeroMemory(pbTempPlaintextBuffer, tempPlaintextBuffer.Length); } } } }
/// <summary> /// Converts an <see cref="ISecret"/> to an <masterKey> element which is marked /// as requiring encryption. /// </summary> /// <param name="secret">The secret for accessing the master key.</param> /// <returns>The master key <see cref="XElement"/>.</returns> public static XElement ToMasterKeyElement(this ISecret secret) { // Technically we'll be keeping the unprotected secret around in memory as // a string, so it can get moved by the GC, but we should be good citizens // and try to pin / clear our our temporary buffers regardless. byte[] unprotectedSecretRawBytes = new byte[secret.Length]; string unprotectedSecretAsBase64String; fixed(byte *__unused__ = unprotectedSecretRawBytes) { try { secret.WriteSecretIntoBuffer(new ArraySegment <byte>(unprotectedSecretRawBytes)); unprotectedSecretAsBase64String = Convert.ToBase64String(unprotectedSecretRawBytes); } finally { Array.Clear(unprotectedSecretRawBytes, 0, unprotectedSecretRawBytes.Length); } } var masterKeyElement = new XElement("masterKey", new XComment(" Warning: the key below is in an unencrypted form. "), new XElement("value", unprotectedSecretAsBase64String)); masterKeyElement.MarkAsRequiresEncryption(); return(masterKeyElement); }
public static byte[] ProtectWithDpapiNG(ISecret secret, NCryptDescriptorHandle protectionDescriptorHandle) { Debug.Assert(secret != null); Debug.Assert(protectionDescriptorHandle != null); var plaintextSecret = new byte[secret.Length]; fixed(byte *pbPlaintextSecret = plaintextSecret) { try { secret.WriteSecretIntoBuffer(new ArraySegment <byte>(plaintextSecret)); byte dummy; // used to provide a valid memory address if secret is zero-length return(ProtectWithDpapiNGCore( protectionDescriptorHandle: protectionDescriptorHandle, pbData: (pbPlaintextSecret != null) ? pbPlaintextSecret : &dummy, cbData: (uint)plaintextSecret.Length)); } finally { // Limits secret exposure to garbage collector. Array.Clear(plaintextSecret, 0, plaintextSecret.Length); } } }
public static byte[] ProtectWithDpapi(ISecret secret, bool protectToLocalMachine = false) { Debug.Assert(secret != null); byte[] plaintextSecret = new byte[secret.Length]; fixed (byte* pbPlaintextSecret = plaintextSecret) { try { secret.WriteSecretIntoBuffer(new ArraySegment<byte>(plaintextSecret)); fixed (byte* pbPurpose = _purpose) { return ProtectWithDpapiCore(pbPlaintextSecret, (uint)plaintextSecret.Length, pbPurpose, (uint)_purpose.Length, fLocalMachine: protectToLocalMachine); } } finally { // To limit exposure to the GC. Array.Clear(plaintextSecret, 0, plaintextSecret.Length); } } }
public static byte[] ProtectWithDpapi(ISecret secret, bool protectToLocalMachine = false) { Debug.Assert(secret != null); byte[] plaintextSecret = new byte[secret.Length]; fixed(byte *pbPlaintextSecret = plaintextSecret) { try { secret.WriteSecretIntoBuffer(new ArraySegment <byte>(plaintextSecret)); fixed(byte *pbPurpose = _purpose) { return(ProtectWithDpapiCore(pbPlaintextSecret, (uint)plaintextSecret.Length, pbPurpose, (uint)_purpose.Length, fLocalMachine: protectToLocalMachine)); } } finally { // To limit exposure to the GC. Array.Clear(plaintextSecret, 0, plaintextSecret.Length); } } }
private XElement EncryptSecret(IXmlEncryptor encryptor) { // First, create the inner <secret> element. XElement secretElement; byte[] plaintextSecret = new byte[_secret.Length]; try { _secret.WriteSecretIntoBuffer(new ArraySegment <byte>(plaintextSecret)); secretElement = new XElement(SecretElementName, Convert.ToBase64String(plaintextSecret)); } finally { Array.Clear(plaintextSecret, 0, plaintextSecret.Length); } // Then encrypt it and wrap it in another <secret> element. var encryptedSecretElement = encryptor.Encrypt(secretElement); CryptoUtil.Assert(!String.IsNullOrEmpty((string)encryptedSecretElement.Attribute("decryptor")), @"TODO: <secret> encryption was invalid."); return(new XElement(SecretElementName, encryptedSecretElement)); }
public static byte[] ProtectWithDpapiNG(ISecret secret, NCryptDescriptorHandle protectionDescriptorHandle) { Debug.Assert(secret != null); Debug.Assert(protectionDescriptorHandle != null); byte[] plaintextSecret = new byte[secret.Length]; fixed (byte* pbPlaintextSecret = plaintextSecret) { try { secret.WriteSecretIntoBuffer(new ArraySegment<byte>(plaintextSecret)); byte dummy; // used to provide a valid memory address if secret is zero-length return ProtectWithDpapiNGCore( protectionDescriptorHandle: protectionDescriptorHandle, pbData: (pbPlaintextSecret != null) ? pbPlaintextSecret : &dummy, cbData: (uint)plaintextSecret.Length); } finally { // Limits secret exposure to garbage collector. Array.Clear(plaintextSecret, 0, plaintextSecret.Length); } } }
/// <summary> /// Creates a new Secret from another secret object. /// </summary> public Secret(ISecret secret) { if (secret == null) { throw new ArgumentNullException(nameof(secret)); } Secret other = secret as Secret; if (other != null) { // Fast-track: simple deep copy scenario. this._localAllocHandle = other._localAllocHandle.Duplicate(); this._plaintextLength = other._plaintextLength; } else { // Copy the secret to a temporary managed buffer, then protect the buffer. // We pin the temp buffer and zero it out when we're finished to limit exposure of the secret. byte[] tempPlaintextBuffer = new byte[secret.Length]; fixed (byte* pbTempPlaintextBuffer = tempPlaintextBuffer) { try { secret.WriteSecretIntoBuffer(new ArraySegment<byte>(tempPlaintextBuffer)); _localAllocHandle = Protect(pbTempPlaintextBuffer, (uint)tempPlaintextBuffer.Length); _plaintextLength = (uint)tempPlaintextBuffer.Length; } finally { UnsafeBufferUtil.SecureZeroMemory(pbTempPlaintextBuffer, tempPlaintextBuffer.Length); } } } }
private static string SecretToBase64String(ISecret secret) { byte[] secretBytes = new byte[secret.Length]; secret.WriteSecretIntoBuffer(new ArraySegment <byte>(secretBytes)); return(Convert.ToBase64String(secretBytes)); }
private static string SecretToBase64String(ISecret secret) { byte[] secretBytes = new byte[secret.Length]; secret.WriteSecretIntoBuffer(new ArraySegment<byte>(secretBytes)); return Convert.ToBase64String(secretBytes); }