国产aaa免费视频国产,日韩一区二区不卡中文字幕,日产精品一二三四区国产,69频道,精品亚洲成a人片在线观看,伊人福利视频,欧美线在线精品观看视频

威勢網(wǎng)絡,為您的企業(yè)和團隊注入互聯(lián)網(wǎng)活力!
服務熱線:138-9741-0341

[原創(chuàng)] C# .NetCore 跨平臺RSA加密實現(xiàn)

發(fā)布日期:2022/11/10 作者: 瀏覽:895

    注意,文中提到的代碼由于時間原因,沒有經過嚴格跨平臺測試,只是編譯通過,在本地windows平臺下測試正常。其它平臺大家自行測試,如有時間,本人后面測試完后再來更新此文。

    相信很多朋友.NetCore下使用RSA時,如下圖所示,都是用的這個第三方NuGet包

    這個包用起來確實很方便,它可以很方便的生成密鑰對供我們調用,也可以很方便的實現(xiàn)RSA加密和解密。網(wǎng)上搜索到的結果基本上都是它的。本以為我也可以這樣風平浪靜心安理得的一直使用,但是直到有一天,我把它引入了一個項目,發(fā)現(xiàn)它上面有個黃色的警告。提示更新,但明明已經是最新版本了,這讓原本就九年義務教育不合格的我束手無策。。。項目發(fā)布以后也莫明其妙的報錯,網(wǎng)上查詢的結果是.NET版本不匹配之類的,懷疑和它有關,于是決定替換了它。本以為這是一件很簡單的事情,沒想到實現(xiàn)起來還是浪費了不少時間。

    本來以為網(wǎng)上有很多現(xiàn)成的輪子拿來直接用就OK了,沒想到搜索到的幾乎全是BouncyCastle.NetCore的, 國外技術論壇上面也搜索到了一些.NET自帶的System.Security.Cryptography的相關結果,但都是只言片語,看的人云里霧里,頭昏奶漲的,不知其所以然。當翻看了MS官方的文檔后看到MS這樣介紹,為了跨平臺,

You should avoid using RSACryptoServiceProvider as it is tightly bound to the Windows platform. Instead, we'll be using the RSA base class, which will return a platform-specific RSA implementation

  要盡量用基類開發(fā),以更好的為平臺解耦。網(wǎng)上搜索的好多代碼都是以前ASP.NET框架下的,如果移植到。netcore下過來,WINDOWS平臺下就算沒問題,其它平臺下也會報錯,閱讀了一些老外的討論,再加上MS官網(wǎng)說明,大概了解到,能用 System.Security.Cryptography.RSA.Create() 的時候,盡量用RSA.Create(),而 new RSACryptoServiceProvider(2048) 方法能不用就不用?;谝陨闲枨?,簡單寫一個類,實現(xiàn)以下功能:

 public class RSAService
    {
        private RSA rsa = RSA.Create();
        public RSAService() { }
        public RSAService(string PubKey_Base64String,string PriKey_Base64String)

      //......省略若干行
 }

初始化構造函數(shù)RSAService,用公鑰私鑰初始化RSA對象

public (string, string) CreateKeyPair   //向調用者返回一對密鑰對

public string PriKey()//返回成員rsa的私鑰

public string PubKey()  //返回公鑰

public string Encrypt(string plainText) //對象對加密明文

public string Decrypt(string cipherText)  //對象內解密密文

public  string Decrypt(string privateKey, string cipherText) //解密對象外密文,即,傳遞一條密鑰和一條密文,由密鑰解出密文

   因為我的需求很簡單,就是前端加密,后端能解密就可以了,所以代碼也是相對簡單。但是在調試的過程中其實還是浪費了不少周折。因為前臺是用JS加密,用AJAX發(fā)送的,JS用/js/jsencrypt.js 這一個好像就夠了。因為RSA算法所限,加密密文不可以超過117個(1024位時),所以長的明文要分段加密才可以。另外,.NETCORE生成的密鑰也分很多類型,什么PEM之類的,還有PKCS1\PKCS8之類的,PKCS8又分帶密碼的,不帶密碼的,拼寫也相近,眼神不好,一看走眼就浪費半天時間,大家調試的時候注意一點,這里值得強調的一點就是,.NETCORE生成的PKCS1的密鑰對,返回前臺JS調用的時候,加密直接返回FALSE,為此浪費了我不少時間,開始以為是自己COPY密鑰的時候是因為格式轉換引起的,所以一頓查找,浪費不少時間,后來才發(fā)現(xiàn),是PKCS1的密鑰不受JS支持,所以我們返回的時候要向前臺返回PKCS8格式的。廢話不多說,以下是代碼:

此處內容僅對會員開放,非會員用戶打賞后才可以查看
相關的JS分段加密代碼如下:


<script>
    function EncryptPost(data,url){
        var returnData;
        $.ajax({
                beforeSend: function (xhr) {
                    if($("#inbox").val().length>113)
                    {
                    }
                },
                type: "get",
                async: false,
                url: '/api/cer/GetPublicKey',
                success: function (_data) {
                    var cid=_data.cid;
                    var encrypt = new JSEncrypt();
                    encrypt.setPublicKey('-----BEGIN PUBLIC KEY-----' + _data.spbKey + '-----END PUBLIC KEY-----');
                    var encrypted = encrypt.encrypt(JSON.stringify(data));
                    $.ajax({
                        url:url,
                        type: "post",
                        data:JSON.stringify({"cid":cid, "json": Base64.encode(encrypted) }),
                        dataType: "json",
                        contentType:"application/json",
                        async: false,
                        success: function (data) {
                            returnData= data;
                        }
                    });
                },
                error: function (msg) {
                    alert('遇到網(wǎng)絡錯誤');
                }
            });
        return returnData;
    }
    function mod(n, m) {
        return ((n % m) + m) % m;
    }
    function splitencrypt(str,spbKey)
    {
        if(str=="") return "";
        if(str.length>117)//1024位密鑰要改成117
        {

            var strArr = [];
            var n = 117;
            var encrypt = new JSEncrypt();
            encrypt.setPublicKey('-----BEGIN PUBLIC KEY-----' + spbKey + '-----END PUBLIC KEY-----');
            for (var i = 0, l = str.length; i < l/n; i++) {
                var a = str.slice(n*i, n*(i+1));
                strArr.push(a);
                if(i==0)
                {
                    //c= encrypt.encrypt(JSON.stringify(a));
                    c= encrypt.encrypt(a);
                }
                else
                {
                    //c=c+"|"+encrypt.encrypt(JSON.stringify(a));
                    c=c+"|"+encrypt.encrypt(a);
                }
            }
            return c;
        }
        else
        {
            var encrypt = new JSEncrypt();
            encrypt.setPublicKey('-----BEGIN PUBLIC KEY-----' + spbKey + '-----END PUBLIC KEY-----');
            return encrypt.encrypt(str);
        }
    }
    $(document).ready(function(){

        $("#de2").click(function(){     
                //這是要發(fā)送的內容
                var data = {
                    "username":"admin",
                    "password": "123465",
                    "age":18
                };
                $("#inbox").text("待發(fā)送數(shù)據(jù):" + JSON.stringify(data));
                var result= EncryptPost(data, "/api/cer/ReciveDemoURL");
                $("#outbox").text(result.Msg+result.content);
            });
        $("#en").click(function() {
            if (($("#pbk").val() == "") || ($("#inbox").val() == "")) { alert("公鑰和待加密字符串不能為空!"); }
            var txt = Base64.encode($("#inbox").val());
            var pbk = Base64.decode($("#pbk").val());
            var inbox=splitencrypt(txt,pbk);
            $("#inbox").val(inbox);
         });

        $("#de").click(function(){
            if (($("#inbox").val() == "") ||($("#prk").val() == "")){ alert("待解密密文和私鑰都不能為空"); }
            $.ajax({
                beforeSend: function (xhr) {
                },
                type: "post",
                url: '/api/cer/UnRSA',  
                data:{Base64EncodeString:Base64.encode($("#inbox").val()),Base64PRKey:$("#prk").val()},//發(fā)送前BASE64編碼,減少出錯。收到后記得decode回來
                dataType: "json",
                success: function (data) {
                   if(data.Result!="Error") { $("#outbox").val(Base64.decode(data.content));}
                   else{
                       $("#outbox").val("解密失敗!"+data.content);
                   }
                },
                error: function (msg) {
                    alert('遇到網(wǎng)絡錯誤');
                }
            });        
        });


        $("#getkey").click(function () {                
            $.ajax({
                    beforeSend: function (xhr) {
                    },
                    type: "get",
                    async: false,
                    url: '/api/cer/GetRsaPairKey',
                    headers: { "RequestVerificationToken": $('@Html.AntiForgeryToken()').val() },
                    success: function (_data) {
                        if (_data.spbKey != undefined) {
                            $("#pbk").text(Base64.encode(_data.spbKey));
                            $("#prk").text(Base64.encode(_data.sprKey));
                            $("#inbox").text("AABBCCDDaabbccdd");
                        }
                        else {
                            alert('請刷新頁面重試');
                        }
                    },
                    error: function (msg) {
                        alert('遇到網(wǎng)絡錯誤');
                    }
                });
        });
    });
</script>

簡單說明,點擊登錄的時候,AJAX用同步提交的方法向服務器臨時拿回一個RSA公鑰,然后將需要發(fā)送的內容加密后,分段加密后發(fā)送到服務器

 原創(chuàng)代碼,轉載請注明出處,翻版必究。


下拉加載更多評論
最新評論
暫無!