/// <summary> /// Encrypts the message using RSA PKCS#1 v1.5 encryption. /// </summary> private ArraySegment <byte> Rsa_Encrypt( ArraySegment <byte> dataToEncrypt, ArraySegment <byte> headerToCopy, X509Certificate2 encryptingCertificate, bool useOaep) { RSA rsa = null; try { // get the encrypting key. rsa = encryptingCertificate.GetRSAPublicKey(); if (rsa == null) { throw ServiceResultException.Create(StatusCodes.BadSecurityChecksFailed, "No public key for certificate."); } int inputBlockSize = RsaUtils.GetPlainTextBlockSize(rsa, useOaep); int outputBlockSize = RsaUtils.GetCipherTextBlockSize(rsa, useOaep); // verify the input data is the correct block size. if (dataToEncrypt.Count % inputBlockSize != 0) { Utils.Trace("Message is not an integral multiple of the block size. Length = {0}, BlockSize = {1}.", dataToEncrypt.Count, inputBlockSize); } byte[] encryptedBuffer = BufferManager.TakeBuffer(SendBufferSize, "Rsa_Encrypt"); Array.Copy(headerToCopy.Array, headerToCopy.Offset, encryptedBuffer, 0, headerToCopy.Count); using (MemoryStream ostrm = new MemoryStream( encryptedBuffer, headerToCopy.Count, encryptedBuffer.Length - headerToCopy.Count)) { // encrypt body. byte[] input = new byte[inputBlockSize]; for (int ii = dataToEncrypt.Offset; ii < dataToEncrypt.Offset + dataToEncrypt.Count; ii += inputBlockSize) { Array.Copy(dataToEncrypt.Array, ii, input, 0, input.Length); if (useOaep == true) { byte[] cipherText = rsa.Encrypt(input, RSAEncryptionPadding.OaepSHA1); ostrm.Write(cipherText, 0, cipherText.Length); } else { byte[] cipherText = rsa.Encrypt(input, RSAEncryptionPadding.Pkcs1); ostrm.Write(cipherText, 0, cipherText.Length); } } } // return buffer return(new ArraySegment <byte>(encryptedBuffer, 0, (dataToEncrypt.Count / inputBlockSize) * outputBlockSize + headerToCopy.Count)); } finally { RsaUtils.RSADispose(rsa); } }
/// <summary> /// Returns the plain text block size for key in the specified certificate. /// </summary> protected int GetPlainTextBlockSize(X509Certificate2 receiverCertificate) { switch (SecurityPolicyUri) { case SecurityPolicies.Basic256: case SecurityPolicies.Basic256Sha256: case SecurityPolicies.Aes128_Sha256_RsaOaep: { return(RsaUtils.GetPlainTextBlockSize(receiverCertificate, RsaUtils.Padding.OaepSHA1)); } case SecurityPolicies.Aes256_Sha256_RsaPss: { return(RsaUtils.GetPlainTextBlockSize(receiverCertificate, RsaUtils.Padding.OaepSHA256)); } case SecurityPolicies.Basic128Rsa15: { return(RsaUtils.GetPlainTextBlockSize(receiverCertificate, RsaUtils.Padding.Pkcs1)); } default: case SecurityPolicies.None: { return(1); } } }
private static bool VerifyRSAKeyPairSign( RSA rsaPublicKey, RSA rsaPrivateKey) { Opc.Ua.Test.RandomSource randomSource = new Opc.Ua.Test.RandomSource(); int blockSize = RsaUtils.GetPlainTextBlockSize(rsaPrivateKey, true); byte[] testBlock = new byte[blockSize]; randomSource.NextBytes(testBlock, 0, blockSize); byte[] signature = rsaPrivateKey.SignData(testBlock, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); return(rsaPublicKey.VerifyData(testBlock, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)); }
/// <summary> /// Decrypts the message using RSA encryption. /// </summary> private ArraySegment <byte> Rsa_Decrypt( ArraySegment <byte> dataToDecrypt, ArraySegment <byte> headerToCopy, X509Certificate2 encryptingCertificate, RsaUtils.Padding padding) { // get the encrypting key. using (RSA rsa = encryptingCertificate.GetRSAPrivateKey()) { if (rsa == null) { throw ServiceResultException.Create(StatusCodes.BadSecurityChecksFailed, "No private key for certificate."); } int inputBlockSize = RsaUtils.GetCipherTextBlockSize(rsa, padding); int outputBlockSize = RsaUtils.GetPlainTextBlockSize(rsa, padding); // verify the input data is the correct block size. if (dataToDecrypt.Count % inputBlockSize != 0) { Utils.Trace("Message is not an integral multiple of the block size. Length = {0}, BlockSize = {1}.", dataToDecrypt.Count, inputBlockSize); } byte[] decryptedBuffer = BufferManager.TakeBuffer(SendBufferSize, "Rsa_Decrypt"); Array.Copy(headerToCopy.Array, headerToCopy.Offset, decryptedBuffer, 0, headerToCopy.Count); RSAEncryptionPadding rsaPadding = RsaUtils.GetRSAEncryptionPadding(padding); using (MemoryStream ostrm = new MemoryStream( decryptedBuffer, headerToCopy.Count, decryptedBuffer.Length - headerToCopy.Count)) { // decrypt body. byte[] input = new byte[inputBlockSize]; for (int ii = dataToDecrypt.Offset; ii < dataToDecrypt.Offset + dataToDecrypt.Count; ii += inputBlockSize) { Array.Copy(dataToDecrypt.Array, ii, input, 0, input.Length); byte[] plainText = rsa.Decrypt(input, rsaPadding); ostrm.Write(plainText, 0, plainText.Length); } } // return buffers. return(new ArraySegment <byte>(decryptedBuffer, 0, (dataToDecrypt.Count / inputBlockSize) * outputBlockSize + headerToCopy.Count)); } }
private static bool VerifyRSAKeyPairCrypt( RSA rsaPublicKey, RSA rsaPrivateKey) { Opc.Ua.Test.RandomSource randomSource = new Opc.Ua.Test.RandomSource(); int blockSize = RsaUtils.GetPlainTextBlockSize(rsaPrivateKey, true); byte[] testBlock = new byte[blockSize]; randomSource.NextBytes(testBlock, 0, blockSize); byte[] encryptedBlock = rsaPublicKey.Encrypt(testBlock, RSAEncryptionPadding.OaepSHA1); byte[] decryptedBlock = rsaPrivateKey.Decrypt(encryptedBlock, RSAEncryptionPadding.OaepSHA1); if (decryptedBlock != null) { return(Utils.IsEqual(testBlock, decryptedBlock)); } return(false); }
/// <summary> /// Verify RSA key pair of two certificates. /// </summary> private static bool VerifyRSAKeyPair( X509Certificate2 certWithPublicKey, X509Certificate2 certWithPrivateKey, bool throwOnError = false) { bool result = false; try { // verify the public and private key match using (RSA rsaPrivateKey = certWithPrivateKey.GetRSAPrivateKey()) { using (RSA rsaPublicKey = certWithPublicKey.GetRSAPublicKey()) { Opc.Ua.Test.RandomSource randomSource = new Opc.Ua.Test.RandomSource(); int blockSize = RsaUtils.GetPlainTextBlockSize(rsaPrivateKey, true); byte[] testBlock = new byte[blockSize]; randomSource.NextBytes(testBlock, 0, blockSize); byte[] encryptedBlock = rsaPublicKey.Encrypt(testBlock, RSAEncryptionPadding.OaepSHA1); byte[] decryptedBlock = rsaPrivateKey.Decrypt(encryptedBlock, RSAEncryptionPadding.OaepSHA1); if (decryptedBlock != null) { result = Utils.IsEqual(testBlock, decryptedBlock); } } } } catch (Exception e) { if (throwOnError) { throw e; } } finally { if (!result && throwOnError) { throw new CryptographicException("The public/private key pair in the certficates do not match."); } } return(result); }
/// <summary> /// Returns the plain text block size for key in the specified certificate. /// </summary> protected int GetPlainTextBlockSize(X509Certificate2 receiverCertificate) { switch (SecurityPolicyUri) { case SecurityPolicies.Basic256: case SecurityPolicies.Basic256Sha256: { return(RsaUtils.GetPlainTextBlockSize(receiverCertificate, true)); } case SecurityPolicies.Basic128Rsa15: { return(RsaUtils.GetPlainTextBlockSize(receiverCertificate, false)); } default: case SecurityPolicies.None: { return(1); } } }