兼容javascript和C#的RSA加密解密算法,对web提交的数据进行加密传输

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: 微软的C#中虽然有RSA算法,但是格式和OpenSSL生成的公钥/私钥文件格式并不兼容。这个也给贯通前后台的RSA加密解密带来了难度。为了兼容OpenSSL生成的公钥/私钥文件格式,贯通javascript和C#的RSA加密解密算法,必须对C#内置的方法进行再度封装。

  Web应用中往往涉及到敏感的数据,由于HTTP协议以明文的形式与服务器进行交互,因此可以通过截获请求的数据包进行分析来盗取有用的信息。虽然https可以对传输的数据进行加密,但是必须要申请证书(一般都是收费的),成本较高。那么问题来了,如果对web提交的敏感数据进行加密呢?web应用中,前端的数据处理和交互基本上都是靠javascript来完成,后台的逻辑处理可以C#(java)等进行处理。

  微软的C#中虽然有RSA算法,但是格式和OpenSSL生成的公钥/私钥文件格式并不兼容。这个也给贯通前后台的RSA加密解密带来了难度。为了兼容OpenSSL生成的公钥/私钥文件格式,贯通javascript和C#的RSA加密解密算法,必须对C#内置的方法进行再度封装。

   下面以登录为例,用户在密码框输入密码后,javascript发送ajax请求时,对密码先进行rsa加密后再发送,服务器接收到加密后的密码后,先对其进行解密, 然后再验证登录是否成功。

 1  为了进行RSA加密解密,首先需要用openssl生成一对公钥和私钥(没有的先下载openssl):

1) 打开openssl.exe文件,输入 genrsa -out openssl_rsa_priv.pem 1024

76497-20161107163648295-1668761517.png

此命令在openssl.exe同目录下生成openssl_rsa_private_key.pem文件。

 2) 生成公钥 rsa  -in openssl_rsa__private.pem -pubout -out openssl_rsa__public.pem

76497-20161107164135842-920775863.png

 以上命令会创建如下的文件:

76497-20161107164255092-2015288419.png

这个文件可以用文本编辑器进行打开,查看内容。

-----BEGINPUBLICKEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC0w036ClSD0LvxPROMun0u022ROJlZE6P3m+gjq3gpi4n7lo8jhTqMqgccDbVJqnIfMzWS9O3lnlQXWTxJ3B4XJ52FAcriY5brOXUVgBLx5QMHLLd1gtJnmG4i7r4ytgX7XVKRnojR6zca1YnS0lbGGDF1CGllB1riNrdksSQP+wIDAQAB-----ENDPUBLICKEY-----
-----BEGINRSAPRIVATEKEY-----MIICXQIBAAKBgQC0w036ClSD0LvxPROMun0u022ROJlZE6P3m+gjq3gpi4n7lo8jhTqMqgccDbVJqnIfMzWS9O3lnlQXWTxJ3B4XJ52FAcriY5brOXUVgBLx5QMHLLd1gtJnmG4i7r4ytgX7XVKRnojR6zca1YnS0lbGGDF1CGllB1riNrdksSQP+wIDAQABAoGAIOyl6lIxXKULZoBKbEqXfIz0GwxlGg1ywyn5mW2lAGQzKMken0ioBnD9xIVWrOlHyhkIvBCyuC0jgfE2Avn93MlB3j0WRuXMFlJpCBlEklMilO9Zgmwl+vTB3VZb8VzdrEEEUBio7LWP/KvSo+IFlNjDTKgAczbLTwAmj4w6g0ECQQDm4yxPdxcU2ywZ7PyjIMM9qnSah9KcrjU8gjEyHsUpgTjhw1cx7Peo+vRiHqxDy1yaSu1BlwRR52pCjKNnl0QhAkEAyGx3NxEIiLk2oXGGbIMZ4P6geC8gYu01BiRNWVf0Yi7+sCH68eUPoI+G5bJ8bvzXpvHjQi0s2OlRfct/qtPQmwJBALa+2DONbxdy4lUi3lO/esk0QVaOaoTY3gomggnJkQRo4zzOABXkGaIF/6gp3u9J5uG4rFFd1m19XP2Pk0ZK1AECQBYilJAKW4zuF7CA3z3AxOzqckKTwdnrJL4G6FwDsMPfONWvCw4IJE+xSk64BbIkTpTrhhPa9WcHba6c+P6e4h0CQQDWeGMMpkqPG/w4afNCGmvRnM8vNkGUAmDGvCsfkTIDijpKl5SD55hPHsWE5rsv1TLUpkWtrFBcg61bHwMUP3cv-----ENDRSAPRIVATEKEY-----

2 用jsencrypt对密码进行加密:

首先需要导入js包文件:

<scriptsrc="dist/js/jsencrypt.js"></script>

然后编写JS加密算法,示例如下:

varencrypt=newJSEncrypt();
varpubkey="-----BEGIN PUBLIC KEY----- \MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAj0dPnBMf3Z4VT1B8Ee6bjKNs \hlYj7xvGijAa8RCdmGR7mrtrExnk8mdUlwdcS05gc4SSFOyWJcYtKUHpWn8/pkS0 \vgGOl9Bzn0Xt9hiqTb3pZAfykNrMDGZMgJgfD6KTnfzVUAOupvxjcGkcoj6/vV5I \eMcx8mT/z3elfsDSjQIDAQAB \-----END PUBLIC KEY-----";
encrypt.setPublicKey(pubkey);
varencrypted=encrypt.encrypt($('#txtpwd').val());
//console.log(encrypted);$.ajax({
type: "POST",
url: "http://localhost:24830/services/rsa_pem.ashx",
data: { "pwd": encrypted },
dataType: "Json",
error: function (xhr, status, error) {
// alert(error);$("#txtInfo").text(' 请求服务器失败!');
$(that).text('登 录');
$(that).attr('disabled', false);
    },
success: function (json) {
if (uid=="admin"&&json.data=="000") {
window.location.href="index.html";
        }
else {
$("#txtInfo").text(' 用户名或者密码错误!');
$(that).text('登 录');
$(that).attr('disabled', false);
        }
    }
});

3 后台用C#进行解密

usingSystem;
usingSystem.Collections.Generic;
usingSystem.IO;
usingSystem.Linq;
usingSystem.Security.Cryptography;
usingSystem.Text;
usingSystem.Threading.Tasks;
namespaceCMCloud.SaaS{
publicclassRSACryptoService    {
privateRSACryptoServiceProvider_privateKeyRsaProvider;
privateRSACryptoServiceProvider_publicKeyRsaProvider;
/// <summary>/// RSA解密/// </summary>/// <param name="cipherText"></param>/// <returns></returns>publicstringDecrypt(stringcipherText)
        {
if (_privateKeyRsaProvider==null)
            {
thrownewException("_privateKeyRsaProvider is null");
            }
returnDecrypt2(cipherText);
        }
/// <summary>/// RSA加密/// </summary>/// <param name="text"></param>/// <returns></returns>publicstringEncrypt(stringtext)
        {
if (_publicKeyRsaProvider==null)
            {
thrownewException("_publicKeyRsaProvider is null");
            }
returnEncrypt2(text);
//return Convert.ToBase64String(_publicKeyRsaProvider.Encrypt(Encoding.UTF8.GetBytes(text), false));        }
privatestringEncrypt2(stringtext)
        {
Byte[] PlaintextData=Encoding.UTF8.GetBytes(text);
intMaxBlockSize=_publicKeyRsaProvider.KeySize/8-11;//加密块最大长度限制if (PlaintextData.Length<=MaxBlockSize)
            {
returnConvert.ToBase64String(_publicKeyRsaProvider.Encrypt(PlaintextData, false));
            }
else            {
using (MemoryStreamPlaiStream=newMemoryStream(PlaintextData))
using (MemoryStreamCrypStream=newMemoryStream())
                {
Byte[] Buffer=newByte[MaxBlockSize];
intBlockSize=PlaiStream.Read(Buffer, 0, MaxBlockSize);
while (BlockSize>0)
                    {
Byte[] ToEncrypt=newByte[BlockSize];
Array.Copy(Buffer, 0, ToEncrypt, 0, BlockSize);
Byte[] Cryptograph=_publicKeyRsaProvider.Encrypt(ToEncrypt, false);
CrypStream.Write(Cryptograph, 0, Cryptograph.Length);
BlockSize=PlaiStream.Read(Buffer, 0, MaxBlockSize);
                    }
returnConvert.ToBase64String(CrypStream.ToArray(), Base64FormattingOptions.None);
                }
            }
        }
privatestringDecrypt2(stringciphertext)
        {
Byte[] CiphertextData=Convert.FromBase64String(ciphertext);
intMaxBlockSize=_privateKeyRsaProvider.KeySize/8;    //解密块最大长度限制if (CiphertextData.Length<=MaxBlockSize)
returnSystem.Text.Encoding.UTF8.GetString(_privateKeyRsaProvider.Decrypt(CiphertextData, false));
using (MemoryStreamCrypStream=newMemoryStream(CiphertextData))
using (MemoryStreamPlaiStream=newMemoryStream())
            {
Byte[] Buffer=newByte[MaxBlockSize];
intBlockSize=CrypStream.Read(Buffer, 0, MaxBlockSize);
while (BlockSize>0)
                {
Byte[] ToDecrypt=newByte[BlockSize];
Array.Copy(Buffer, 0, ToDecrypt, 0, BlockSize);
Byte[] Plaintext=_privateKeyRsaProvider.Decrypt(ToDecrypt, false);
PlaiStream.Write(Plaintext, 0, Plaintext.Length);
BlockSize=CrypStream.Read(Buffer, 0, MaxBlockSize);
                }
returnSystem.Text.Encoding.UTF8.GetString(PlaiStream.ToArray());
            }
        }
publicRSACryptoService(stringprivateKey, stringpublicKey=null)
        {
if (!string.IsNullOrEmpty(privateKey))
            {
_privateKeyRsaProvider=CreateRsaProviderFromPrivateKey(privateKey);
            }
if (!string.IsNullOrEmpty(publicKey))
            {
_publicKeyRsaProvider=CreateRsaProviderFromPublicKey(publicKey);
            }
        }
privateRSACryptoServiceProviderCreateRsaProviderFromPrivateKey(stringprivateKey)
        {
varprivateKeyBits=System.Convert.FromBase64String(privateKey);
varRSA=newRSACryptoServiceProvider();
varRSAparams=newRSAParameters();
using (BinaryReaderbinr=newBinaryReader(newMemoryStream(privateKeyBits)))
            {
bytebt=0;
ushorttwobytes=0;
twobytes=binr.ReadUInt16();
if (twobytes==0x8130)
binr.ReadByte();
elseif (twobytes==0x8230)
binr.ReadInt16();
elsethrownewException("Unexpected value read binr.ReadUInt16()");
twobytes=binr.ReadUInt16();
if (twobytes!=0x0102)
thrownewException("Unexpected version");
bt=binr.ReadByte();
if (bt!=0x00)
thrownewException("Unexpected value read binr.ReadByte()");
RSAparams.Modulus=binr.ReadBytes(GetIntegerSize(binr));
RSAparams.Exponent=binr.ReadBytes(GetIntegerSize(binr));
RSAparams.D=binr.ReadBytes(GetIntegerSize(binr));
RSAparams.P=binr.ReadBytes(GetIntegerSize(binr));
RSAparams.Q=binr.ReadBytes(GetIntegerSize(binr));
RSAparams.DP=binr.ReadBytes(GetIntegerSize(binr));
RSAparams.DQ=binr.ReadBytes(GetIntegerSize(binr));
RSAparams.InverseQ=binr.ReadBytes(GetIntegerSize(binr));
            }
RSA.ImportParameters(RSAparams);
returnRSA;
        }
privateintGetIntegerSize(BinaryReaderbinr)
        {
bytebt=0;
bytelowbyte=0x00;
bytehighbyte=0x00;
intcount=0;
bt=binr.ReadByte();
if (bt!=0x02)
return0;
bt=binr.ReadByte();
if (bt==0x81)
count=binr.ReadByte();
elseif (bt==0x82)
            {
highbyte=binr.ReadByte();
lowbyte=binr.ReadByte();
byte[] modint= { lowbyte, highbyte, 0x00, 0x00 };
count=BitConverter.ToInt32(modint, 0);
            }
else            {
count=bt;
            }
while (binr.ReadByte() ==0x00)
            {
count-=1;
            }
binr.BaseStream.Seek(-1, SeekOrigin.Current);
returncount;
        }
privateRSACryptoServiceProviderCreateRsaProviderFromPublicKey(stringpublicKeyString)
        {
// encoded OID sequence for  PKCS #1 rsaEncryption szOID_RSA_RSA = "1.2.840.113549.1.1.1"byte[] SeqOID= { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };
byte[] x509key;
byte[] seq=newbyte[15];
intx509size;
x509key=Convert.FromBase64String(publicKeyString);
x509size=x509key.Length;
// ---------  Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob  ------using (MemoryStreammem=newMemoryStream(x509key))
            {
using (BinaryReaderbinr=newBinaryReader(mem))  //wrap Memory Stream with BinaryReader for easy reading                {
bytebt=0;
ushorttwobytes=0;
twobytes=binr.ReadUInt16();
if (twobytes==0x8130) //data read as little endian order (actual data order for Sequence is 30 81)binr.ReadByte();    //advance 1 byteelseif (twobytes==0x8230)
binr.ReadInt16();   //advance 2 byteselsereturnnull;
seq=binr.ReadBytes(15);       //read the Sequence OIDif (!CompareBytearrays(seq, SeqOID))    //make sure Sequence for OID is correctreturnnull;
twobytes=binr.ReadUInt16();
if (twobytes==0x8103) //data read as little endian order (actual data order for Bit String is 03 81)binr.ReadByte();    //advance 1 byteelseif (twobytes==0x8203)
binr.ReadInt16();   //advance 2 byteselsereturnnull;
bt=binr.ReadByte();
if (bt!=0x00)     //expect null byte nextreturnnull;
twobytes=binr.ReadUInt16();
if (twobytes==0x8130) //data read as little endian order (actual data order for Sequence is 30 81)binr.ReadByte();    //advance 1 byteelseif (twobytes==0x8230)
binr.ReadInt16();   //advance 2 byteselsereturnnull;
twobytes=binr.ReadUInt16();
bytelowbyte=0x00;
bytehighbyte=0x00;
if (twobytes==0x8102) //data read as little endian order (actual data order for Integer is 02 81)lowbyte=binr.ReadByte();  // read next bytes which is bytes in moduluselseif (twobytes==0x8202)
                    {
highbyte=binr.ReadByte(); //advance 2 byteslowbyte=binr.ReadByte();
                    }
elsereturnnull;
byte[] modint= { lowbyte, highbyte, 0x00, 0x00 };   //reverse byte order since asn.1 key uses big endian orderintmodsize=BitConverter.ToInt32(modint, 0);
intfirstbyte=binr.PeekChar();
if (firstbyte==0x00)
                    {   //if first byte (highest order) of modulus is zero, don't include itbinr.ReadByte();    //skip this null bytemodsize-=1;   //reduce modulus buffer size by 1                    }
byte[] modulus=binr.ReadBytes(modsize);   //read the modulus bytesif (binr.ReadByte() !=0x02)            //expect an Integer for the exponent datareturnnull;
intexpbytes= (int)binr.ReadByte();        // should only need one byte for actual exponent data (for all useful values)byte[] exponent=binr.ReadBytes(expbytes);
// ------- create RSACryptoServiceProvider instance and initialize with public key -----RSACryptoServiceProviderRSA=newRSACryptoServiceProvider();
RSAParametersRSAKeyInfo=newRSAParameters();
RSAKeyInfo.Modulus=modulus;
RSAKeyInfo.Exponent=exponent;
RSA.ImportParameters(RSAKeyInfo);
returnRSA;
                }
            }
        }
privateboolCompareBytearrays(byte[] a, byte[] b)
        {
if (a.Length!=b.Length)
returnfalse;
inti=0;
foreach (bytecina)
            {
if (c!=b[i])
returnfalse;
i++;
            }
returntrue;
        }
    }
}

     虽然将公钥暴露在js文件中,但是如果需要解密得到明文,必须需要私钥(这个存储在后台,不容易获取)。调试运行,可以看到获取的密码是加密后的数据,然后在后台可以进行解密获取到明文。

相关文章
|
2月前
|
算法 安全 数据安全/隐私保护
Android经典实战之常见的移动端加密算法和用kotlin进行AES-256加密和解密
本文介绍了移动端开发中常用的数据加密算法,包括对称加密(如 AES 和 DES)、非对称加密(如 RSA)、散列算法(如 SHA-256 和 MD5)及消息认证码(如 HMAC)。重点讲解了如何使用 Kotlin 实现 AES-256 的加密和解密,并提供了详细的代码示例。通过生成密钥、加密和解密数据等步骤,展示了如何在 Kotlin 项目中实现数据的安全加密。
58 1
|
2月前
|
算法 安全 数据安全/隐私保护
Android经典实战之常见的移动端加密算法和用kotlin进行AES-256加密和解密
本文介绍了移动端开发中常用的数据加密算法,包括对称加密(如 AES 和 DES)、非对称加密(如 RSA)、散列算法(如 SHA-256 和 MD5)及消息认证码(如 HMAC)。重点展示了如何使用 Kotlin 实现 AES-256 的加密和解密,提供了详细的代码示例。
39 2
|
2月前
|
算法 JavaScript 前端开发
国标非对称加密:RSA算法、非对称特征、js还原、jsencrypt和rsa模块解析
国标非对称加密:RSA算法、非对称特征、js还原、jsencrypt和rsa模块解析
130 1
|
2月前
|
算法 JavaScript 前端开发
消息摘要算法:MD5加密
消息摘要算法:MD5加密
47 1
|
3月前
|
算法 安全 数据安全/隐私保护
支付系统---微信支付09------数字签名,现在Bob想要给Pink写一封信,信件的内容不需要加密,怎样能够保证信息的完整性,使用信息完整性的主要手段是摘要算法,散列函数,哈希函数,H称为数据指纹
支付系统---微信支付09------数字签名,现在Bob想要给Pink写一封信,信件的内容不需要加密,怎样能够保证信息的完整性,使用信息完整性的主要手段是摘要算法,散列函数,哈希函数,H称为数据指纹
|
3月前
|
算法 安全 网络安全
支付系统,网络安全06----支付安全---,机密性,加密算法,目前最流行的加密算法,AES加密算法,目前最流行的非对称加密算法RSA,对称加密和非对称加密的优缺点,非对称加密是基于非常复杂的数学算法
支付系统,网络安全06----支付安全---,机密性,加密算法,目前最流行的加密算法,AES加密算法,目前最流行的非对称加密算法RSA,对称加密和非对称加密的优缺点,非对称加密是基于非常复杂的数学算法
|
3天前
|
SQL 安全 算法
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
【9月更文挑战第29天】随着互联网的普及,网络安全问题日益严重。本文将介绍网络安全漏洞、加密技术以及安全意识等方面的内容,帮助读者了解网络安全的重要性,提高自身的网络安全意识。
|
1天前
|
存储 安全 网络安全
揭秘网络安全的盾牌与剑:漏洞防御与加密技术
【9月更文挑战第31天】在数字时代的浪潮中,网络安全和信息安全成为了保护个人隐私和企业资产的重要屏障。本文将通过浅显易懂的语言和生动的比喻,带你深入了解网络安全漏洞、加密技术的奥秘,以及如何培养安全意识。我们将一起探索网络安全的“盾牌”和“剑”,了解它们如何守护我们的数字世界。
105 61
|
2天前
|
SQL 安全 程序员
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
【9月更文挑战第30天】在数字化时代,网络安全和信息安全已成为全球关注的焦点。本文将探讨网络安全漏洞、加密技术以及提升安全意识的重要性。我们将通过代码示例,深入理解网络安全的基础知识,包括常见的网络攻击手段、防御策略和加密技术的实际应用。同时,我们还将讨论如何提高个人和企业的安全意识,以应对日益复杂的网络安全威胁。
|
1天前
|
存储 安全 网络安全
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
【9月更文挑战第31天】在数字化时代,网络安全和信息安全成为了我们生活中不可或缺的一部分。本文将从网络安全漏洞、加密技术和安全意识等方面进行知识分享,帮助读者更好地了解和保护自己的网络安全。
下一篇
无影云桌面