예제 #1
0
        /// <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);
                    }
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Converts an <see cref="ISecret"/> to an &lt;masterKey&gt; 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);
        }
예제 #3
0
        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);
                }
            }
        }
예제 #5
0
        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);
                }
            }
        }
예제 #6
0
        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);
                }
            }
        }
예제 #8
0
        /// <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);
                    }
                }
            }
        }
예제 #9
0
 private static string SecretToBase64String(ISecret secret)
 {
     byte[] secretBytes = new byte[secret.Length];
     secret.WriteSecretIntoBuffer(new ArraySegment <byte>(secretBytes));
     return(Convert.ToBase64String(secretBytes));
 }
예제 #10
0
 private static string SecretToBase64String(ISecret secret)
 {
     byte[] secretBytes = new byte[secret.Length];
     secret.WriteSecretIntoBuffer(new ArraySegment<byte>(secretBytes));
     return Convert.ToBase64String(secretBytes);
 }