Ejemplo n.º 1
0
            public override bool TryEncrypt(ReadOnlySpan <byte> data, Span <byte> destination, RSAEncryptionPadding padding, out int bytesWritten)
            {
                if (padding == null)
                {
                    throw new ArgumentNullException(nameof(padding));
                }

                ThrowIfDisposed();

                int rsaSize = RsaPaddingProcessor.BytesRequiredForBitCount(KeySize);

                if (destination.Length < rsaSize)
                {
                    bytesWritten = 0;
                    return(false);
                }

                if (padding == RSAEncryptionPadding.Pkcs1 && data.Length > 0)
                {
                    const int Pkcs1PaddingOverhead = 11;
                    int       maxAllowed           = rsaSize - Pkcs1PaddingOverhead;

                    if (data.Length > maxAllowed)
                    {
                        throw new CryptographicException(
                                  SR.Format(SR.Cryptography_Encryption_MessageTooLong, maxAllowed));
                    }

                    return(Interop.AppleCrypto.TryRsaEncrypt(
                               GetKeys().PublicKey,
                               data,
                               destination,
                               padding,
                               out bytesWritten));
                }

                RsaPaddingProcessor processor;

                switch (padding.Mode)
                {
                case RSAEncryptionPaddingMode.Pkcs1:
                    processor = null;
                    break;

                case RSAEncryptionPaddingMode.Oaep:
                    processor = RsaPaddingProcessor.OpenProcessor(padding.OaepHashAlgorithm);
                    break;

                default:
                    throw new CryptographicException(SR.Cryptography_InvalidPaddingMode);
                }

                byte[]      rented = CryptoPool.Rent(rsaSize);
                Span <byte> tmp    = new Span <byte>(rented, 0, rsaSize);

                try
                {
                    if (processor != null)
                    {
                        processor.PadOaep(data, tmp);
                    }
                    else
                    {
                        Debug.Assert(padding.Mode == RSAEncryptionPaddingMode.Pkcs1);
                        RsaPaddingProcessor.PadPkcs1Encryption(data, tmp);
                    }

                    return(Interop.AppleCrypto.TryRsaEncryptionPrimitive(
                               GetKeys().PublicKey,
                               tmp,
                               destination,
                               out bytesWritten));
                }
                finally
                {
                    CryptographicOperations.ZeroMemory(tmp);
                    CryptoPool.Return(rented, clearSize: 0);
                }
            }
Ejemplo n.º 2
0
            public override bool TryDecrypt(ReadOnlySpan <byte> data, Span <byte> destination, RSAEncryptionPadding padding, out int bytesWritten)
            {
                if (padding == null)
                {
                    throw new ArgumentNullException(nameof(padding));
                }

                SecKeyPair keys = GetKeys();

                if (keys.PrivateKey == null)
                {
                    throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey);
                }

                return(TryDecrypt(keys.PrivateKey, data, destination, padding, out bytesWritten));
            }
Ejemplo n.º 3
0
        // Conveniently, Encrypt() and Decrypt() are identical save for the actual P/Invoke call to CNG. Thus, both
        // array-based APIs invoke this common helper with the "encrypt" parameter determining whether encryption or decryption is done.
        private unsafe byte[] EncryptOrDecrypt(byte[] data, RSAEncryptionPadding padding, bool encrypt)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }
            if (padding == null)
            {
                throw new ArgumentNullException(nameof(padding));
            }

            int modulusSizeInBytes = RsaPaddingProcessor.BytesRequiredForBitCount(KeySize);

            if (!encrypt && data.Length != modulusSizeInBytes)
            {
                throw new CryptographicException(SR.Cryptography_RSA_DecryptWrongSize);
            }

            if (encrypt &&
                padding.Mode == RSAEncryptionPaddingMode.Pkcs1 &&
                data.Length > modulusSizeInBytes - Pkcs1PaddingOverhead)
            {
                throw new CryptographicException(
                          SR.Format(SR.Cryptography_Encryption_MessageTooLong, modulusSizeInBytes - Pkcs1PaddingOverhead));
            }

            using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle())
            {
                if (encrypt && data.Length == 0)
                {
                    byte[]      rented        = CryptoPool.Rent(modulusSizeInBytes);
                    Span <byte> paddedMessage = new Span <byte>(rented, 0, modulusSizeInBytes);

                    try
                    {
                        if (padding == RSAEncryptionPadding.Pkcs1)
                        {
                            RsaPaddingProcessor.PadPkcs1Encryption(data, paddedMessage);
                        }
                        else if (padding.Mode == RSAEncryptionPaddingMode.Oaep)
                        {
                            RsaPaddingProcessor processor =
                                RsaPaddingProcessor.OpenProcessor(padding.OaepHashAlgorithm);

                            processor.PadOaep(data, paddedMessage);
                        }
                        else
                        {
                            throw new CryptographicException(SR.Cryptography_UnsupportedPaddingMode);
                        }

                        return(EncryptOrDecrypt(keyHandle, paddedMessage, AsymmetricPaddingMode.NCRYPT_NO_PADDING_FLAG, null, encrypt));
                    }
                    finally
                    {
                        CryptographicOperations.ZeroMemory(paddedMessage);
                        CryptoPool.Return(rented, clearSize: 0);
                    }
                }

                switch (padding.Mode)
                {
                case RSAEncryptionPaddingMode.Pkcs1:
                    return(EncryptOrDecrypt(keyHandle, data, AsymmetricPaddingMode.NCRYPT_PAD_PKCS1_FLAG, null, encrypt));

                case RSAEncryptionPaddingMode.Oaep:
                    IntPtr namePtr = Marshal.StringToHGlobalUni(padding.OaepHashAlgorithm.Name);
                    try
                    {
                        var paddingInfo = new BCRYPT_OAEP_PADDING_INFO()
                        {
                            pszAlgId = namePtr,

                            // It would nice to put randomized data here but RSAEncryptionPadding does not at this point provide support for this.
                            pbLabel = IntPtr.Zero,
                            cbLabel = 0,
                        };
                        return(EncryptOrDecrypt(keyHandle, data, AsymmetricPaddingMode.NCRYPT_PAD_OAEP_FLAG, &paddingInfo, encrypt));
                    }
                    finally
                    {
                        Marshal.FreeHGlobal(namePtr);
                    }

                default:
                    throw new CryptographicException(SR.Cryptography_UnsupportedPaddingMode);
                }
            }
        }
Ejemplo n.º 4
0
 public virtual byte[] Encrypt(byte[] data, RSAEncryptionPadding padding)
 {
     throw RSA.DerivedClassMustOverride();
 }
Ejemplo n.º 5
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="input"></param>
 /// <param name="privateKey_xml">密钥</param>
 /// <param name="encryptionPadding">OaepSHA1|OaepSHA256|OaepSHA384|OaepSHA512|Pkcs1</param>
 /// <returns></returns>
 public static byte[] RSADecrypt(this byte[] input, Stream privateKey_xml, RSAEncryptionPadding encryptionPadding)
 => RSADecrypt_(input, privateKey_xml, encryptionPadding);
Ejemplo n.º 6
0
 /// <summary>Decrypts data using the private key.</summary>
 public override bool TryDecrypt(ReadOnlySpan <byte> data, Span <byte> destination, RSAEncryptionPadding padding, out int bytesWritten) =>
 TryEncryptOrDecrypt(data, destination, padding, encrypt: false, bytesWritten: out bytesWritten);
Ejemplo n.º 7
0
        public override bool TryEncrypt(ReadOnlySpan <byte> data, Span <byte> destination, RSAEncryptionPadding padding, out int bytesWritten)
        {
            if (padding == null)
            {
                throw new ArgumentNullException(nameof(padding));
            }

            ValidatePadding(padding);
            SafeEvpPKeyHandle?key = GetKey();

            return(TryEncrypt(key, data, destination, padding, out bytesWritten));
        }
Ejemplo n.º 8
0
 public virtual byte[] Decrypt(byte[] data, RSAEncryptionPadding padding) => throw DerivedClassMustOverride();
Ejemplo n.º 9
0
 public abstract byte[] Decrypt(byte[] data, RSAEncryptionPadding padding);
Ejemplo n.º 10
0
        public override bool TryDecrypt(
            ReadOnlySpan <byte> data,
            Span <byte> destination,
            RSAEncryptionPadding padding,
            out int bytesWritten)
        {
            if (padding == null)
            {
                throw new ArgumentNullException(nameof(padding));
            }

            ValidatePadding(padding);
            SafeEvpPKeyHandle key = GetKey();
            int keySizeBytes      = Interop.Crypto.EvpPKeySize(key);

            // OpenSSL requires that the decryption buffer be at least as large as EVP_PKEY_size.
            // So if the destination is too small, use a temporary buffer so we can match
            // Windows behavior of succeeding so long as the buffer can hold the final output.
            if (destination.Length < keySizeBytes)
            {
                // RSA up through 4096 bits use a stackalloc
                Span <byte> tmp = stackalloc byte[512];
                byte[]? rent = null;

                if (keySizeBytes > tmp.Length)
                {
                    rent = CryptoPool.Rent(keySizeBytes);
                    tmp  = rent;
                }

                int  written = Decrypt(key, data, tmp, padding);
                bool ret;

                if (destination.Length < written)
                {
                    bytesWritten = 0;
                    ret          = false;
                }
                else
                {
                    tmp.Slice(0, written).CopyTo(destination);
                    bytesWritten = written;
                    ret          = true;
                }

                // Whether a stackalloc or a rented array, clear our copy of
                // the decrypted content.
                CryptographicOperations.ZeroMemory(tmp.Slice(0, written));

                if (rent != null)
                {
                    // Already cleared.
                    CryptoPool.Return(rent, clearSize: 0);
                }

                return(ret);
            }

            bytesWritten = Decrypt(key, data, destination, padding);
            return(true);
        }
Ejemplo n.º 11
0
            public override bool TryEncrypt(ReadOnlySpan <byte> data, Span <byte> destination, RSAEncryptionPadding padding, out int bytesWritten)
            {
                if (padding == null)
                {
                    throw new ArgumentNullException(nameof(padding));
                }

                int rsaSize = RsaPaddingProcessor.BytesRequiredForBitCount(KeySize);

                if (destination.Length < rsaSize)
                {
                    bytesWritten = 0;
                    return(false);
                }

                if (padding == RSAEncryptionPadding.Pkcs1 && data.Length > 0)
                {
                    return(Interop.AppleCrypto.TryRsaEncrypt(
                               GetKeys().PublicKey,
                               data,
                               destination,
                               padding,
                               out bytesWritten));
                }

                RsaPaddingProcessor processor;

                switch (padding.Mode)
                {
                case RSAEncryptionPaddingMode.Pkcs1:
                    processor = null;
                    break;

                case RSAEncryptionPaddingMode.Oaep:
                    processor = RsaPaddingProcessor.OpenProcessor(padding.OaepHashAlgorithm);
                    break;

                default:
                    throw new CryptographicException(SR.Cryptography_InvalidPaddingMode);
                }

                byte[] rented = ArrayPool <byte> .Shared.Rent(rsaSize);

                Span <byte> tmp = new Span <byte>(rented, 0, rsaSize);

                try
                {
                    if (processor != null)
                    {
                        processor.PadOaep(data, tmp);
                    }
                    else
                    {
                        Debug.Assert(padding.Mode == RSAEncryptionPaddingMode.Pkcs1);
                        RsaPaddingProcessor.PadPkcs1Encryption(data, tmp);
                    }

                    return(Interop.AppleCrypto.TryRsaEncryptionPrimitive(
                               GetKeys().PublicKey,
                               tmp,
                               destination,
                               out bytesWritten));
                }
                finally
                {
                    tmp.Clear();
                    ArrayPool <byte> .Shared.Return(rented);
                }
            }
Ejemplo n.º 12
0
            public override bool TryEncrypt(ReadOnlySpan <byte> data, Span <byte> destination, RSAEncryptionPadding padding, out int bytesWritten)
            {
                ArgumentNullException.ThrowIfNull(padding);

                Interop.AndroidCrypto.RsaPadding rsaPadding = GetInteropPadding(padding);
                SafeRsaHandle key = GetKey();

                return(TryEncrypt(key, data, destination, rsaPadding, out bytesWritten));
            }
Ejemplo n.º 13
0
        // Conveniently, Encrypt() and Decrypt() are identical save for the actual P/Invoke call to CNG. Thus, both
        // span-based APIs invoke this common helper with the "encrypt" parameter determining whether encryption or decryption is done.
        private unsafe bool TryEncryptOrDecrypt(ReadOnlySpan <byte> data, Span <byte> destination, RSAEncryptionPadding padding, bool encrypt, out int bytesWritten)
        {
            if (padding == null)
            {
                throw new ArgumentNullException(nameof(padding));
            }

            using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle())
            {
                switch (padding.Mode)
                {
                case RSAEncryptionPaddingMode.Pkcs1:
                    return(TryEncryptOrDecrypt(keyHandle, data, destination, AsymmetricPaddingMode.NCRYPT_PAD_PKCS1_FLAG, null, encrypt, out bytesWritten));

                case RSAEncryptionPaddingMode.Oaep:
                    IntPtr namePtr = Marshal.StringToHGlobalUni(padding.OaepHashAlgorithm.Name);
                    try
                    {
                        var paddingInfo = new BCRYPT_OAEP_PADDING_INFO()
                        {
                            pszAlgId = namePtr,
                            pbLabel  = IntPtr.Zero,    // It would nice to put randomized data here but RSAEncryptionPadding does not at this point provide support for this.
                            cbLabel  = 0,
                        };
                        return(TryEncryptOrDecrypt(keyHandle, data, destination, AsymmetricPaddingMode.NCRYPT_PAD_OAEP_FLAG, &paddingInfo, encrypt, out bytesWritten));
                    }
                    finally
                    {
                        Marshal.FreeHGlobal(namePtr);
                    }

                default:
                    throw new CryptographicException(SR.Cryptography_UnsupportedPaddingMode);
                }
            }
        }
Ejemplo n.º 14
0
        public override bool TryDecrypt(
            ReadOnlySpan <byte> data,
            Span <byte> destination,
            RSAEncryptionPadding padding,
            out int bytesWritten)
        {
            if (padding == null)
            {
                throw new ArgumentNullException(nameof(padding));
            }

            Interop.Crypto.RsaPadding rsaPadding = GetInteropPadding(padding, out RsaPaddingProcessor oaepProcessor);
            SafeRsaHandle             key        = GetKey();

            int keySizeBytes = Interop.Crypto.RsaSize(key);

            // OpenSSL does not take a length value for the destination, so it can write out of bounds.
            // To prevent the OOB write, decrypt into a temporary buffer.
            if (destination.Length < keySizeBytes)
            {
                Span <byte> tmp  = stackalloc byte[0];
                byte[]      rent = null;

                // RSA up through 4096 stackalloc
                if (keySizeBytes <= 512)
                {
                    tmp = stackalloc byte[keySizeBytes];
                }
                else
                {
                    rent = ArrayPool <byte> .Shared.Rent(keySizeBytes);

                    tmp = rent;
                }

                bool ret = TryDecrypt(key, data, tmp, rsaPadding, oaepProcessor, out bytesWritten);

                if (ret)
                {
                    tmp = tmp.Slice(0, bytesWritten);

                    if (bytesWritten > destination.Length)
                    {
                        ret          = false;
                        bytesWritten = 0;
                    }
                    else
                    {
                        tmp.CopyTo(destination);
                    }

                    CryptographicOperations.ZeroMemory(tmp);
                }

                if (rent != null)
                {
                    // Already cleared
                    ArrayPool <byte> .Shared.Return(rent);
                }

                return(ret);
            }

            return(TryDecrypt(key, data, destination, rsaPadding, oaepProcessor, out bytesWritten));
        }
Ejemplo n.º 15
0
 /// <summary>Encrypts data using the public key.</summary>
 public override byte[] Encrypt(byte[] data, RSAEncryptionPadding padding) =>
 EncryptOrDecrypt(data, padding, encrypt: true);
Ejemplo n.º 16
0
        public override bool TryEncrypt(ReadOnlySpan <byte> data, Span <byte> destination, RSAEncryptionPadding padding, out int bytesWritten)
        {
            if (padding == null)
            {
                throw new ArgumentNullException(nameof(padding));
            }

            Interop.Crypto.RsaPadding rsaPadding = GetInteropPadding(padding, out RsaPaddingProcessor oaepProcessor);
            SafeRsaHandle             key        = GetKey();

            return(TryEncrypt(key, data, destination, rsaPadding, oaepProcessor, out bytesWritten));
        }
Ejemplo n.º 17
0
 /// <summary>Decrypts data using the private key.</summary>
 public override unsafe byte[] Decrypt(byte[] data, RSAEncryptionPadding padding) =>
 EncryptOrDecrypt(data, padding, encrypt: false);
Ejemplo n.º 18
0
        public virtual bool TryEncrypt(ReadOnlySpan <byte> data, Span <byte> destination, RSAEncryptionPadding padding, out int bytesWritten)
        {
            byte[] result = Encrypt(data.ToArray(), padding);

            if (destination.Length >= result.Length)
            {
                new ReadOnlySpan <byte>(result).CopyTo(destination);
                bytesWritten = result.Length;
                return(true);
            }

            bytesWritten = 0;
            return(false);
        }
Ejemplo n.º 19
0
 public override byte[] Encrypt(byte[] data, RSAEncryptionPadding padding)
 {
     return(Interop.AppleCrypto.RsaEncrypt(GetKeys().PublicKey, data, padding));
 }