.net core RSA 分段加密解密,簽名驗籤(對接java)

參考地址:html

http://www.javashuo.com/article/p-hsfrtrha-m.htmljava

http://www.javashuo.com/article/p-guigbega-md.htmlnode

https://github.com/stulzq/RSAExtensions(XC.RSAUtil)  git

http://www.javashuo.com/article/p-upapmlxk-kz.html github

https://github.com/stulzq/RSAExtensions (RSAExtension)算法

 

參考以上的案例能夠解決在.net core 中的RSA加密解密(包括分段),簽名驗籤。spring

實際對接Java 時要根據Java的具體作法,作一些更改以適用於對接。apache

一、首先java是怎麼作的呢?提供一個java rsa 的工具類app

package com.card.psbc.facility.utils.xmlSignature; import com.sun.org.apache.xerces.internal.impl.dv.util.Base64; import javax.crypto.Cipher; import java.io.*; import java.security.*; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map; /** * @Auther: * @Description: //TODO RSA2048加密 --若是須要改爲1024的,須要改下生成方法的密鑰長度並從新生成,而後MAX_DECRYPT_BLOCK改爲128就能夠了 * @Date: **/
public class RSAUtil2048 { //加密算法RSA
    public static final String KEY_ALGORITHM = "RSA"; //簽名算法
    public static final String SIGNATURE_ALGORITHM = "MD5withRSA"; //獲取公鑰的key
    private static final String PUBLIC_KEY = "RSAPublicKey"; //獲取私鑰的key
    private static final String PRIVATE_KEY = "RSAPrivateKey"; //RSA最大加密明文大小
    private static final int MAX_ENCRYPT_BLOCK = 117; //RSA最大解密密文大小
    private static final int MAX_DECRYPT_BLOCK = 256; /** * @return void * @Author: * @Description: //TODO 生成密鑰對(公鑰和私鑰)文件並保存本地 下面的生成方法和這個差很少 只是不保存和初始密鑰長度的地方有所區別 * @Date: * @Param: [filePath] 保存文件路徑 **/
    public static void genKeyPairByFilePath(String filePath) throws Exception { //KeyPairGenerator祕鑰構成器,也就是能夠生成一對祕鑰,能夠是公鑰也能夠是私鑰,因此大部分用在非對稱加密中 getInstance()設置密鑰的格式
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM); //使用給定的隨機源(和默認的參數集合)初始化肯定密鑰長度的密鑰對生成器 SecureRandom()隨機源
        keyPairGenerator.initialize(2048, new SecureRandom()); //generateKeyPair()生成密鑰對
        KeyPair keyPair = keyPairGenerator.generateKeyPair(); //強轉成公鑰
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); //強轉成私鑰
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); //二進制轉字符串
        String publicKeyString = Base64.encode(publicKey.getEncoded()); //二進制轉字符串
        String privateKeyString = Base64.encode(privateKey.getEncoded()); //下面是保存方法
        BufferedWriter publicbw = new BufferedWriter(new FileWriter(new File(filePath + "/publicKey"))); BufferedWriter privatebw = new BufferedWriter(new FileWriter(new File(filePath + "/privateKey"))); publicbw.write(publicKeyString); privatebw.write(privateKeyString); publicbw.flush(); publicbw.close(); privatebw.flush(); privatebw.close(); } /** * @return java.util.Map<java.lang.String, java.lang.Object> * @Author: * @Description: //TODO 生成密鑰對(公鑰和私鑰) * @Date: **/
    public static Map<String, Object> genKeyPair() throws Exception { //祕鑰構成器,也就是能夠生成一對祕鑰,能夠是公鑰也能夠是私鑰,因此大部分用在非對稱加密中
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM); //設定密鑰的大小整數值
        keyPairGen.initialize(2048); //generateKeyPair()生成密鑰對
        KeyPair keyPair = keyPairGen.generateKeyPair(); //強轉成公鑰
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); //強轉成私鑰
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); Map<String, Object> keyMap = new HashMap<String, Object>(2); keyMap.put(PUBLIC_KEY, publicKey); keyMap.put(PRIVATE_KEY, privateKey); return keyMap; } /** * @Author: * @Description: //TODO 從文件中讀取公鑰或私鑰 * @Date: * @Param: [filePath] * @return java.lang.String **/
    public static String readKeyFromFile(String filePath) { try { BufferedReader br = new BufferedReader(new FileReader(new File(filePath))); String readLine = null; StringBuilder sb = new StringBuilder(); while ((readLine = br.readLine()) != null) { sb.append(readLine); } br.close(); return sb.toString(); } catch (IOException e) { e.printStackTrace(); } return null; }

    /** * @param data 已加密數據 * @param privateKey 私鑰(BASE64編碼) * @return java.lang.String * @Author: * @Description: //TODO 私鑰加簽 * @Date: **/
    public static String sign(byte[] data, String privateKey) throws Exception { //字符串解碼爲二進制數據
        byte[] keyBytes = Base64Utils.decode(privateKey); //私鑰的ASN.1編碼規範
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); //KeyFactory通常經過本身的靜態方法keyFactory.generatePublic()得到;
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); //根據給定的密鑰材料生成私鑰對象
        PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec); //Signature類用作簽名的,通常經過本身的靜態方法getInstance("算法名稱")獲取
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); //經過傳入的私鑰初始化待簽名對象
 signature.initSign(privateK); //更新待簽名或驗證的數據
 signature.update(data); //返回全部已更新的簽名字節
        return Base64Utils.encode(signature.sign()); } /** * @param data 已加密數據 * @param publicKey 公鑰(BASE64編碼) * @param sign 數字簽名 * @return boolean * @Author: * @Description: //TODO 公鑰驗籤 * @Date: **/
    public static boolean verify(byte[] data, String publicKey, String sign) throws Exception { //字符串解碼爲二進制數據
        byte[] keyBytes = Base64Utils.decode(publicKey); //密鑰的X509編碼
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); //KeyFactory通常經過本身的靜態方法keyFactory.generatePublic()得到;
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); //根據給定的密鑰材料生成公鑰對象
        PublicKey publicK = keyFactory.generatePublic(keySpec); //Signature類用作簽名的,通常經過本身的靜態方法getInstance("算法名稱")獲取
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); //經過給定的公鑰初始化對象
 signature.initVerify(publicK); //更新待簽名或驗證的數據
 signature.update(data); //驗證待傳入的簽名
        return signature.verify(Base64Utils.decode(sign)); } /** * @param data 源數據 * @param publicKey 公鑰(BASE64編碼) * @return java.lang.String * @Author: * @Description: //TODO 公鑰加密 * @Date: **/
    public static String encryptByPublicKey(byte[] data, String publicKey) throws Exception { byte[] keyBytes = org.springframework.util.Base64Utils.decodeFromString(publicKey); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key publicK = keyFactory.generatePublic(keySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, publicK); int inputLen = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 對數據分段加密
        while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); } else { cache = cipher.doFinal(data, offSet, inputLen - offSet); } out.write(cache); i++; offSet = i * MAX_ENCRYPT_BLOCK; } byte[] encryptedData = out.toByteArray(); String s = org.springframework.util.Base64Utils.encodeToString(encryptedData); // System.out.println(s+"=====================================================");
 out.close(); return s; } /** * @param encryptedData 已加密數據 * @return byte[] * @Author: * @Description: //TODO 私鑰解密 * @Date: **/
    public static byte[] decryptByPrivateKey(String encryptedData, String privateKey) throws Exception { byte[] keyBytes = Base64Utils.decode(privateKey); byte[] data = org.springframework.util.Base64Utils.decodeFromString(encryptedData); PKCS8EncodedKeySpec x509KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key publicK = keyFactory.generatePrivate(x509KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, publicK); int inputLen = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 對數據分段解密
        while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_DECRYPT_BLOCK) { cache = cipher.doFinal(data, offSet, MAX_DECRYPT_BLOCK); } else { cache = cipher.doFinal(data, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_DECRYPT_BLOCK; } byte[] decryptedData = out.toByteArray(); out.close(); return decryptedData; } /** * @param data 源數據 * @param privateKey 私鑰(BASE64編碼) * @return java.lang.String * @Author: * @Description: //TODO 私鑰加密 * @Date: **/
    public static String encryptByPrivateKey(byte[] data, String privateKey) throws Exception { byte[] keyBytes = Base64Utils.decode(privateKey); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key privateK = keyFactory.generatePrivate(pkcs8KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, privateK); int inputLen = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 對數據分段加密
        while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); } else { cache = cipher.doFinal(data, offSet, inputLen - offSet); } out.write(cache); i++; offSet = i * MAX_ENCRYPT_BLOCK; } byte[] encryptedData = out.toByteArray(); String s = org.springframework.util.Base64Utils.encodeToString(encryptedData); // System.out.println(s+"=====================================================");
 out.close(); return s; } /** * @param encryptedData 已加密數據 * @param publicKey 公鑰(BASE64編碼) * @return byte[] * @Author: * @Description: //TODO 公鑰解密 * @Date: **/
    public static byte[] decryptByPublicKey(String encryptedData, String publicKey) throws Exception { byte[] keyBytes = Base64Utils.decode(publicKey); byte[] data = org.springframework.util.Base64Utils.decodeFromString(encryptedData); X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key publicK = keyFactory.generatePublic(x509KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, publicK); int inputLen = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 對數據分段解密
        while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_DECRYPT_BLOCK) { cache = cipher.doFinal(data, offSet, MAX_DECRYPT_BLOCK); } else { cache = cipher.doFinal(data, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_DECRYPT_BLOCK; } byte[] decryptedData = out.toByteArray(); out.close(); return decryptedData; } }

二、.net core 如何來作 ?dom

using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Security; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Xml; namespace Asmkt.Transmit.Core.Utilities { /// <summary>
    /// RSA加解密 使用OpenSSL的公鑰加密/私鑰解密 /// 做者:李志強 /// 建立時間:2017年10月30日15:50:14 /// QQ:501232752 /// </summary>
    public class RSAHelper3 { private readonly RSA _privateKeyRsaProvider; private readonly RSA _publicKeyRsaProvider; private readonly HashAlgorithmName _hashAlgorithmName; private readonly Encoding _encoding; /// <summary>
        /// 實例化RSAHelper /// </summary>
        /// <param name="rsaType">加密算法類型 RSA SHA1;RSA2 SHA256 密鑰長度至少爲2048</param>
        /// <param name="encoding">編碼類型</param>
        /// <param name="privateKey">私鑰</param>
        /// <param name="publicKey">公鑰</param>
        public RSAHelper3(RSAType rsaType, Encoding encoding, string privateKey, string publicKey = null) { _encoding = encoding; if (!string.IsNullOrEmpty(privateKey)) { _privateKeyRsaProvider = CreateRsaProviderFromPrivateKey(privateKey); } if (!string.IsNullOrEmpty(publicKey)) { _publicKeyRsaProvider = CreateRsaProviderFromPublicKey(publicKey); } _hashAlgorithmName = HashAlgorithmName.SHA256; if (rsaType == RSAType.RSA) { _hashAlgorithmName = HashAlgorithmName.SHA1; } if (rsaType == RSAType.RSA2) { _hashAlgorithmName = HashAlgorithmName.SHA256; } if (rsaType == RSAType.MD5) { _hashAlgorithmName = HashAlgorithmName.MD5; } } #region 使用私鑰簽名

        /// <summary>
        /// 使用私鑰簽名 /// </summary>
        /// <param name="data">原始數據</param>
        /// <returns></returns>
        public string Sign(string data) { byte[] dataBytes = _encoding.GetBytes(data); var signatureBytes = _privateKeyRsaProvider.SignData(dataBytes, _hashAlgorithmName, RSASignaturePadding.Pkcs1); return Convert.ToBase64String(signatureBytes); } #endregion

        #region 使用公鑰驗證簽名

        /// <summary>
        /// 使用公鑰驗證簽名 /// </summary>
        /// <param name="data">原始數據</param>
        /// <param name="sign">簽名</param>
        /// <returns></returns>
        public bool Verify(string data, string sign) { byte[] dataBytes = _encoding.GetBytes(data); var dataSign = sign.Replace(" ", "+"); int mod4 = dataSign.Length % 4; if (mod4 > 0) { dataSign += new string('=', 4 - mod4); } byte[] signBytes = Convert.FromBase64String(dataSign); var verify = _publicKeyRsaProvider.VerifyData(dataBytes, signBytes, _hashAlgorithmName, RSASignaturePadding.Pkcs1); return verify; } #endregion

        #region 解密

        public string Decrypt(string cipherText) { if (_privateKeyRsaProvider == null) { throw new Exception("_privateKeyRsaProvider is null"); } return Encoding.UTF8.GetString(_privateKeyRsaProvider.Decrypt(Convert.FromBase64String(cipherText), RSAEncryptionPadding.Pkcs1)); } public string DecryptBigData(string dataStr) { //privateKey = RsaPrivateKeyJava2DotNet(privateKey); //FromXmlStringExtensions(rsa, privateKey);

            var data = dataStr.Split(new char[] { '$' }, StringSplitOptions.RemoveEmptyEntries); var byteList = new List<byte>(); foreach (var item in data) { byteList.AddRange(_privateKeyRsaProvider.Decrypt(Convert.FromBase64String(item), RSAEncryptionPadding.Pkcs1)); } return Encoding.UTF8.GetString(byteList.ToArray()); } public string DecryptBigDataJava(string dataStr) { //privateKey = RsaPrivateKeyJava2DotNet(privateKey); //FromXmlStringExtensions(rsa, privateKey);
 dataStr = dataStr.Replace(" ", "+"); int mod4 = dataStr.Length % 4; if (mod4 > 0) { dataStr += new string('=', 4 - mod4); } var byteList = new List<byte>(); var data = Convert.FromBase64String(dataStr); var splitLength = 128; var splitsNumber = Convert.ToInt32(Math.Ceiling(data.Length * 1.0 / splitLength)); var pointer = 0; for (int i = 0; i < splitsNumber; i++) { if (pointer + splitLength < data.Length) { byte[] current = data.Skip(pointer).Take(splitLength).ToArray(); byteList.AddRange(_privateKeyRsaProvider.Decrypt(current, RSAEncryptionPadding.Pkcs1)); pointer += splitLength; } else { byte[] current = data.Skip(pointer).Take(splitLength).ToArray(); byteList.AddRange(_privateKeyRsaProvider.Decrypt(current, RSAEncryptionPadding.Pkcs1)); pointer += splitLength; } //byte[] current = pointer + splitLength < data.Length ? data[pointer..(pointer + splitLength)] : data[pointer..];
 } return Encoding.UTF8.GetString(byteList.ToArray()); } #endregion

        #region 加密

        public string Encrypt(string text) { if (_publicKeyRsaProvider == null) { throw new Exception("_publicKeyRsaProvider is null"); } return Convert.ToBase64String(_publicKeyRsaProvider.Encrypt(Encoding.UTF8.GetBytes(text), RSAEncryptionPadding.Pkcs1)); } public string EncryptBigData(string dataStr) { char connChar = '$'; //publicKey = RsaPublicKeyJava2DotNet(publicKey); //FromXmlStringExtensions(rsa, publicKey);

            var data = Encoding.UTF8.GetBytes(dataStr); //var modulusLength = _publicKeyRsaProvider.KeySize / 8; //var splitLength = modulusLength - PaddingLimitDic[padding];
            var splitLength = 117; var sb = new StringBuilder(); var splitsNumber = Convert.ToInt32(Math.Ceiling(data.Length * 1.0 / splitLength)); var pointer = 0; for (int i = 0; i < splitsNumber; i++) { if (pointer + splitLength < data.Length) { byte[] current = data.Skip(pointer).Take(splitLength).ToArray(); sb.Append(Convert.ToBase64String(_publicKeyRsaProvider.Encrypt(current, RSAEncryptionPadding.Pkcs1))); sb.Append(connChar); pointer += splitLength; } else { byte[] current = data.Skip(pointer).Take(data.Length - pointer).ToArray(); sb.Append(Convert.ToBase64String(_publicKeyRsaProvider.Encrypt(current, RSAEncryptionPadding.Pkcs1))); sb.Append(connChar); pointer += splitLength; } //byte[] current = pointer + splitLength < data.Length ? data[pointer..(pointer + splitLength)] : data[pointer..];
 } return sb.ToString(); } public string EncryptBigDataJava(string dataStr) { //publicKey = RsaPublicKeyJava2DotNet(publicKey); //FromXmlStringExtensions(rsa, publicKey);

            var data = Encoding.UTF8.GetBytes(dataStr); //var modulusLength = _publicKeyRsaProvider.KeySize / 8; //var splitLength = modulusLength - PaddingLimitDic[padding];
            var splitLength = 117; var byteList = new List<byte>(); var splitsNumber = Convert.ToInt32(Math.Ceiling(data.Length * 1.0 / splitLength)); var pointer = 0; for (int i = 0; i < splitsNumber; i++) { if (pointer + splitLength < data.Length) { byte[] current = data.Skip(pointer).Take(splitLength).ToArray(); byteList.AddRange(_publicKeyRsaProvider.Encrypt(current, RSAEncryptionPadding.Pkcs1)); pointer += splitLength; } else { byte[] current = data.Skip(pointer).Take(data.Length - pointer).ToArray(); byteList.AddRange(_publicKeyRsaProvider.Encrypt(current, RSAEncryptionPadding.Pkcs1)); pointer += splitLength; } //byte[] current = pointer + splitLength < data.Length ? data[pointer..(pointer + splitLength)] : data[pointer..];
 } return Convert.ToBase64String(byteList.ToArray()); } #endregion

        #region 使用私鑰建立RSA實例

        public RSA CreateRsaProviderFromPrivateKey(string privateKey) { var privateKeyBits = Convert.FromBase64String(privateKey); var rsa = RSA.Create(); var rsaParameters = new RSAParameters(); using (BinaryReader binr = new BinaryReader(new MemoryStream(privateKeyBits))) { byte bt = 0; ushort twobytes = 0; twobytes = binr.ReadUInt16(); if (twobytes == 0x8130) binr.ReadByte(); else if (twobytes == 0x8230) binr.ReadInt16(); else
                    throw new Exception("Unexpected value read binr.ReadUInt16()"); twobytes = binr.ReadUInt16(); if (twobytes != 0x0102) throw new Exception("Unexpected version"); bt = binr.ReadByte(); if (bt != 0x00) throw new Exception("Unexpected value read binr.ReadByte()"); rsaParameters.Modulus = binr.ReadBytes(GetIntegerSize(binr)); rsaParameters.Exponent = binr.ReadBytes(GetIntegerSize(binr)); rsaParameters.D = binr.ReadBytes(GetIntegerSize(binr)); rsaParameters.P = binr.ReadBytes(GetIntegerSize(binr)); rsaParameters.Q = binr.ReadBytes(GetIntegerSize(binr)); rsaParameters.DP = binr.ReadBytes(GetIntegerSize(binr)); rsaParameters.DQ = binr.ReadBytes(GetIntegerSize(binr)); rsaParameters.InverseQ = binr.ReadBytes(GetIntegerSize(binr)); } rsa.ImportParameters(rsaParameters); return rsa; } #endregion

        #region 使用公鑰建立RSA實例

        public RSA CreateRsaProviderFromPublicKey(string publicKeyString) { // 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[] seq = new byte[15]; var x509Key = Convert.FromBase64String(publicKeyString); // --------- Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob ------
            using (MemoryStream mem = new MemoryStream(x509Key)) { using (BinaryReader binr = new BinaryReader(mem))  //wrap Memory Stream with BinaryReader for easy reading
 { byte bt = 0; ushort twobytes = 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 byte
                    else if (twobytes == 0x8230) binr.ReadInt16(); //advance 2 bytes
                    else
                        return null; seq = binr.ReadBytes(15);       //read the Sequence OID
                    if (!CompareBytearrays(seq, seqOid))    //make sure Sequence for OID is correct
                        return null; 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 byte
                    else if (twobytes == 0x8203) binr.ReadInt16(); //advance 2 bytes
                    else
                        return null; bt = binr.ReadByte(); if (bt != 0x00)     //expect null byte next
                        return null; twobytes = binr.ReadUInt16(); if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
                        binr.ReadByte();    //advance 1 byte
                    else if (twobytes == 0x8230) binr.ReadInt16(); //advance 2 bytes
                    else
                        return null; twobytes = binr.ReadUInt16(); byte lowbyte = 0x00; byte highbyte = 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 modulus
                    else if (twobytes == 0x8202) { highbyte = binr.ReadByte(); //advance 2 bytes
                        lowbyte = binr.ReadByte(); } else
                        return null; byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };   //reverse byte order since asn.1 key uses big endian order
                    int modsize = BitConverter.ToInt32(modint, 0); int firstbyte = binr.PeekChar(); if (firstbyte == 0x00) { //if first byte (highest order) of modulus is zero, don't include it
                        binr.ReadByte();    //skip this null byte
                        modsize -= 1;   //reduce modulus buffer size by 1
 } byte[] modulus = binr.ReadBytes(modsize);   //read the modulus bytes

                    if (binr.ReadByte() != 0x02)            //expect an Integer for the exponent data
                        return null; int expbytes = (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 -----
                    var rsa = RSA.Create(); RSAParameters rsaKeyInfo = new RSAParameters { Modulus = modulus, Exponent = exponent }; rsa.ImportParameters(rsaKeyInfo); return rsa; } } } #endregion

        #region 導入密鑰算法

        private int GetIntegerSize(BinaryReader binr) { byte bt = 0; int count = 0; bt = binr.ReadByte(); if (bt != 0x02) return 0; bt = binr.ReadByte(); if (bt == 0x81) count = binr.ReadByte(); else
            if (bt == 0x82) { var highbyte = binr.ReadByte(); var 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); return count; } private bool CompareBytearrays(byte[] a, byte[] b) { if (a.Length != b.Length) return false; int i = 0; foreach (byte c in a) { if (c != b[i]) return false; i++; } return true; } #endregion

        static readonly Dictionary<RSAEncryptionPadding, int> PaddingLimitDic = new Dictionary<RSAEncryptionPadding, int>() { [RSAEncryptionPadding.Pkcs1] = 11, [RSAEncryptionPadding.OaepSHA1] = 42, [RSAEncryptionPadding.OaepSHA256] = 66, [RSAEncryptionPadding.OaepSHA384] = 98, [RSAEncryptionPadding.OaepSHA512] = 130, }; /// <summary>
        /// private key ,java->.net /// </summary>
        /// <param name="privateKey"></param>
        /// <returns></returns>
        public static string RsaPrivateKeyJava2DotNet(string privateKey) { if (string.IsNullOrEmpty(privateKey)) { return string.Empty; } var privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKey)); return $"<RSAKeyValue><Modulus>{Convert.ToBase64String(privateKeyParam.Modulus.ToByteArrayUnsigned())}</Modulus><Exponent>{Convert.ToBase64String(privateKeyParam.PublicExponent.ToByteArrayUnsigned())}</Exponent><P>{Convert.ToBase64String(privateKeyParam.P.ToByteArrayUnsigned())}</P><Q>{Convert.ToBase64String(privateKeyParam.Q.ToByteArrayUnsigned())}</Q><DP>{Convert.ToBase64String(privateKeyParam.DP.ToByteArrayUnsigned())}</DP><DQ>{Convert.ToBase64String(privateKeyParam.DQ.ToByteArrayUnsigned())}</DQ><InverseQ>{Convert.ToBase64String(privateKeyParam.QInv.ToByteArrayUnsigned())}</InverseQ><D>{Convert.ToBase64String(privateKeyParam.Exponent.ToByteArrayUnsigned())}</D></RSAKeyValue>"; } /// <summary>
        /// 擴展FromXmlString /// </summary>
        /// <param name="rsa"></param>
        /// <param name="xmlString"></param>
        private static void FromXmlStringExtensions(RSA rsa, string xmlString) { var parameters = new RSAParameters(); var xmlDoc = new XmlDocument(); xmlDoc.LoadXml(xmlString); if (xmlDoc.DocumentElement.Name.Equals("RSAKeyValue")) { foreach (XmlNode node in xmlDoc.DocumentElement.ChildNodes) { switch (node.Name) { case "Modulus": parameters.Modulus = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; case "Exponent": parameters.Exponent = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; case "P": parameters.P = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; case "Q": parameters.Q = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; case "DP": parameters.DP = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; case "DQ": parameters.DQ = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; case "InverseQ": parameters.InverseQ = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; case "D": parameters.D = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; } } } else { throw new Exception("Invalid XML RSA key."); } rsa.ImportParameters(parameters); } /// <summary>
        /// public key ,java->.net /// </summary>
        /// <param name="publicKey"></param>
        /// <returns>格式轉換結果</returns>
        public static string RsaPublicKeyJava2DotNet(string publicKey) { if (string.IsNullOrEmpty(publicKey)) { return string.Empty; } var publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey)); return string.Format( "<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>", Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()), Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned()) ); } } /// <summary>
    /// RSA算法類型 /// </summary>
    public enum RSAType { /// <summary>
        /// SHA1 /// </summary>
        RSA = 0, /// <summary>
        /// RSA2 密鑰長度至少爲2048 /// SHA256 /// </summary>
        RSA2 = 1, MD5 = 2 } }

三、詳細解釋:

   一、分段加密解密:參考中的.net core分段加密解密使用 ‘$’ 來做爲分段的標識,而java 中沒有,所以關鍵在於解密時找準分段的大小即代碼中的 splitLength,加密時爲117 ,而這個數字可由 

    var modulusLength = _publicKeyRsaProvider.KeySize / 8;     var splitLength = modulusLength - PaddingLimitDic[padding];

  來計算,當前寫死;解密時爲128,不要問我怎麼來的,我是調試加密代碼時,debug出來的。望有大佬給個理論的說法?

二、加簽驗籤:這裏有個坑爲 加簽驗籤時的算法名稱 HashAlgorithmName 必定要一致,java中爲MD5,對應 .net core 也要MD5,。上面的的代碼能夠改進一下,能夠改爲靜態方法,暴露出 HashAlgorithmName  參數

 

以上踩坑,Over!

相關文章
相關標籤/搜索