c java互通rsa_C#原生代码实现与java互通的RSA加解密及签名认证(SHA1WithRSA)

usingSystem;usingSystem.Collections.Generic;usingSystem.IO;usingSystem.Linq;usingSystem.Security.Cryptography;usingSystem.Text;usingSystem.Threading.Tasks;namespaceXin.Common.Tool

{///

///类名:RSAFromPkcs8///功能:RSA加密、解密、签名、验签 (支持1024位和2048位私钥)///详细:该类对Java生成的密钥进行解密和签名以及验签专用类,不需要修改///

public sealed classRSAUtil_PKCS

{/**

* RSA最大解密密文大小

* 注意:这个和密钥长度有关系, 公式= 密钥长度 / 8*/

private const int MAX_DECRYPT_BLOCK = 128;///

///签名///

/// 待签名字符串

/// 编码格式

/// 签名后字符串

public static string sign(string content, string privateKey, stringinput_charset)

{byte[] Data =Encoding.GetEncoding(input_charset).GetBytes(content);

RSACryptoServiceProvider rsa=DecodePemPrivateKey(privateKey);

SHA1 sh= newSHA1CryptoServiceProvider();byte[] signData =rsa.SignData(Data, sh);returnConvert.ToBase64String(signData);

}///

///验签///

/// 待验签字符串

/// 签名

/// 编码格式

/// true(通过),false(不通过)

public static bool verify(string content, string signedString, string publicKey, stringinput_charset)

{bool result = false;byte[] Data =Encoding.GetEncoding(input_charset).GetBytes(content);byte[] data =Convert.FromBase64String(signedString);

RSAParameters paraPub=ConvertFromPublicKey(publicKey);

RSACryptoServiceProvider rsaPub= newRSACryptoServiceProvider();

rsaPub.ImportParameters(paraPub);

SHA1 sh= newSHA1CryptoServiceProvider();

result=rsaPub.VerifyData(Data, sh, data);returnresult;

}///

///加密///

/// 需要加密的字符串

/// 编码格式

/// 明文

public static string encryptData(string resData, string publicKey, stringinput_charset)

{byte[] DataToEncrypt =Encoding.ASCII.GetBytes(resData);string result =encrypt(DataToEncrypt, publicKey, input_charset);returnresult;

}///

///解密///

/// 加密字符串

/// 私钥

/// 编码格式

/// 明文

public static string decryptData(string resData, string privateKey, stringinput_charset)

{byte[] DataToDecrypt =Convert.FromBase64String(resData);string result = "";for (int j = 0; j < DataToDecrypt.Length / MAX_DECRYPT_BLOCK; j++)

{byte[] buf = new byte[MAX_DECRYPT_BLOCK];for (int i = 0; i < MAX_DECRYPT_BLOCK; i++)

{

buf[i]= DataToDecrypt[i + MAX_DECRYPT_BLOCK *j];

}

result+=decrypt(buf, privateKey, input_charset);

}returnresult;

}#region 内部方法

private static string encrypt(byte[] data, string publicKey, stringinput_charset)

{

RSACryptoServiceProvider rsa=DecodePemPublicKey(publicKey);

SHA1 sh= newSHA1CryptoServiceProvider();byte[] result = rsa.Encrypt(data, false);returnConvert.ToBase64String(result);

}private static string decrypt(byte[] data, string privateKey, stringinput_charset)

{string result = "";

RSACryptoServiceProvider rsa=DecodePemPrivateKey(privateKey);//--- Edit for testing by lzyan ---//RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();//RSAParameters paraPri = ConvertFromPrivateKey(privateKey);//rsa.ImportParameters(paraPri);//--- Edit End ---

SHA1 sh= newSHA1CryptoServiceProvider();byte[] source = rsa.Decrypt(data, false);char[] asciiChars = new char[Encoding.GetEncoding(input_charset).GetCharCount(source, 0, source.Length)];

Encoding.GetEncoding(input_charset).GetChars(source,0, source.Length, asciiChars, 0);

result= new string(asciiChars);//result = ASCIIEncoding.ASCII.GetString(source);

returnresult;

}private static RSACryptoServiceProvider DecodePemPublicKey(stringpemstr)

{byte[] pkcs8publickkey;

pkcs8publickkey=Convert.FromBase64String(pemstr);if (pkcs8publickkey != null)

{

RSACryptoServiceProvider rsa=DecodeRSAPublicKey(pkcs8publickkey);returnrsa;

}else

return null;

}private static RSACryptoServiceProvider DecodePemPrivateKey(stringpemstr)

{byte[] pkcs8privatekey;

pkcs8privatekey=Convert.FromBase64String(pemstr);if (pkcs8privatekey != null)

{

RSACryptoServiceProvider rsa=DecodePrivateKeyInfo(pkcs8privatekey);returnrsa;

}else

return null;

}private static RSACryptoServiceProvider DecodePrivateKeyInfo(byte[] pkcs8)

{byte[] SeqOID = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00};byte[] seq = new byte[15];

MemoryStream mem= newMemoryStream(pkcs8);int lenstream = (int)mem.Length;

BinaryReader binr= new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading

byte bt = 0;ushort twobytes = 0;try{

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;

bt=binr.ReadByte();if (bt != 0x02)return null;

twobytes=binr.ReadUInt16();if (twobytes != 0x0001)return null;

seq= binr.ReadBytes(15); //read the Sequence OID

if (!CompareBytearrays(seq, SeqOID)) //make sure Sequence for OID is correct

return null;

bt=binr.ReadByte();if (bt != 0x04) //expect an Octet string

return null;

bt= binr.ReadByte(); //read next byte, or next 2 bytes is 0x81 or 0x82; otherwise bt is the byte count

if (bt == 0x81)

binr.ReadByte();else

if (bt == 0x82)

binr.ReadUInt16();//------ at this stage, the remaining sequence should be the RSA private key

byte[] rsaprivkey = binr.ReadBytes((int)(lenstream -mem.Position));

RSACryptoServiceProvider rsacsp=DecodeRSAPrivateKey(rsaprivkey);returnrsacsp;

}catch(Exception)

{return null;

}finally{ binr.Close(); }

}private static bool CompareBytearrays(byte[] a, byte[] b)

{if (a.Length !=b.Length)return false;int i = 0;foreach (byte c ina)

{if (c !=b[i])return false;

i++;

}return true;

}private static RSACryptoServiceProvider DecodeRSAPublicKey(byte[] publickey)

{//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];//--------- Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob ------

MemoryStream mem = newMemoryStream(publickey);

BinaryReader binr= new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading

byte bt = 0;ushort twobytes = 0;try{

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);byte firstbyte =binr.ReadByte();

binr.BaseStream.Seek(-1, SeekOrigin.Current);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 -----

RSACryptoServiceProvider RSA = newRSACryptoServiceProvider();

RSAParameters RSAKeyInfo= newRSAParameters();

RSAKeyInfo.Modulus=modulus;

RSAKeyInfo.Exponent=exponent;

RSA.ImportParameters(RSAKeyInfo);returnRSA;

}catch(Exception)

{return null;

}finally{ binr.Close(); }

}private static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey)

{byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;//--------- Set up stream to decode the asn.1 encoded RSA private key ------

MemoryStream mem = newMemoryStream(privkey);

BinaryReader binr= new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading

byte bt = 0;ushort twobytes = 0;int elems = 0;try{

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();if (twobytes != 0x0102) //version number

return null;

bt=binr.ReadByte();if (bt != 0x00)return null;//------ all private key components are Integer sequences ----

elems =GetIntegerSize(binr);

MODULUS=binr.ReadBytes(elems);

elems=GetIntegerSize(binr);

E=binr.ReadBytes(elems);

elems=GetIntegerSize(binr);

D=binr.ReadBytes(elems);

elems=GetIntegerSize(binr);

P=binr.ReadBytes(elems);

elems=GetIntegerSize(binr);

Q=binr.ReadBytes(elems);

elems=GetIntegerSize(binr);

DP=binr.ReadBytes(elems);

elems=GetIntegerSize(binr);

DQ=binr.ReadBytes(elems);

elems=GetIntegerSize(binr);

IQ=binr.ReadBytes(elems);//------- create RSACryptoServiceProvider instance and initialize with public key -----

RSACryptoServiceProvider RSA = newRSACryptoServiceProvider();

RSAParameters RSAparams= newRSAParameters();

RSAparams.Modulus=MODULUS;

RSAparams.Exponent=E;

RSAparams.D=D;

RSAparams.P=P;

RSAparams.Q=Q;

RSAparams.DP=DP;

RSAparams.DQ=DQ;

RSAparams.InverseQ=IQ;

RSA.ImportParameters(RSAparams);returnRSA;

}catch(Exception)

{return null;

}finally{ binr.Close(); }

}private static intGetIntegerSize(BinaryReader binr)

{byte bt = 0;byte lowbyte = 0x00;byte highbyte = 0x00;int count = 0;

bt=binr.ReadByte();if (bt != 0x02) //expect integer

return 0;

bt=binr.ReadByte();if (bt == 0x81)

count= binr.ReadByte(); //data size in next byte

else

if (bt == 0x82)

{

highbyte= binr.ReadByte(); //data size in next 2 bytes

lowbyte =binr.ReadByte();byte[] modint = { lowbyte, highbyte, 0x00, 0x00};

count= BitConverter.ToInt32(modint, 0);

}else{

count= bt; //we already have the data size

}while (binr.ReadByte() == 0x00)

{//remove high order zeros in data

count -= 1;

}

binr.BaseStream.Seek(-1, SeekOrigin.Current); //last ReadByte wasn't a removed zero, so back up a byte

returncount;

}#endregion

#region 解析.net 生成的Pem

private static RSAParameters ConvertFromPublicKey(stringpemFileConent)

{if (string.IsNullOrEmpty(pemFileConent))

{throw new ArgumentNullException("pemFileConent", "This arg cann't be empty.");

}

pemFileConent= pemFileConent.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", "").Replace("\n", "").Replace("\r", "");byte[] keyData =Convert.FromBase64String(pemFileConent);bool keySize1024 = (keyData.Length == 162);bool keySize2048 = (keyData.Length == 294);if (!(keySize1024 ||keySize2048))

{throw new ArgumentException("pem file content is incorrect, Only support the key size is 1024 or 2048");

}byte[] pemModulus = (keySize1024 ? new byte[128] : new byte[256]);byte[] pemPublicExponent = new byte[3];

Array.Copy(keyData, (keySize1024? 29 : 33), pemModulus, 0, (keySize1024 ? 128 : 256));

Array.Copy(keyData, (keySize1024? 159 : 291), pemPublicExponent, 0, 3);

RSAParameters para= newRSAParameters();

para.Modulus=pemModulus;

para.Exponent=pemPublicExponent;returnpara;

}///

///将pem格式私钥(1024 or 2048)转换为RSAParameters///

/// pem私钥内容

/// 转换得到的RSAParamenters

private static RSAParameters ConvertFromPrivateKey(stringpemFileConent)

{if (string.IsNullOrEmpty(pemFileConent))

{throw new ArgumentNullException("pemFileConent", "This arg cann't be empty.");

}

pemFileConent= pemFileConent.Replace("-----BEGIN RSA PRIVATE KEY-----", "").Replace("-----END RSA PRIVATE KEY-----", "").Replace("\n", "").Replace("\r", "");byte[] keyData =Convert.FromBase64String(pemFileConent);bool keySize1024 = (keyData.Length == 609 || keyData.Length == 610);bool keySize2048 = (keyData.Length == 1190 || keyData.Length == 1192);if (!(keySize1024 ||keySize2048))

{throw new ArgumentException("pem file content is incorrect, Only support the key size is 1024 or 2048");

}int index = (keySize1024 ? 11 : 12);byte[] pemModulus = (keySize1024 ? new byte[128] : new byte[256]);

Array.Copy(keyData, index, pemModulus,0, pemModulus.Length);

index+=pemModulus.Length;

index+= 2;byte[] pemPublicExponent = new byte[3];

Array.Copy(keyData, index, pemPublicExponent,0, 3);

index+= 3;

index+= 4;if ((int)keyData[index] == 0)

{

index++;

}byte[] pemPrivateExponent = (keySize1024 ? new byte[128] : new byte[256]);

Array.Copy(keyData, index, pemPrivateExponent,0, pemPrivateExponent.Length);

index+=pemPrivateExponent.Length;

index+= (keySize1024 ? ((int)keyData[index + 1] == 64 ? 2 : 3) : ((int)keyData[index + 2] == 128 ? 3 : 4));byte[] pemPrime1 = (keySize1024 ? new byte[64] : new byte[128]);

Array.Copy(keyData, index, pemPrime1,0, pemPrime1.Length);

index+=pemPrime1.Length;

index+= (keySize1024 ? ((int)keyData[index + 1] == 64 ? 2 : 3) : ((int)keyData[index + 2] == 128 ? 3 : 4));byte[] pemPrime2 = (keySize1024 ? new byte[64] : new byte[128]);

Array.Copy(keyData, index, pemPrime2,0, pemPrime2.Length);

index+=pemPrime2.Length;

index+= (keySize1024 ? ((int)keyData[index + 1] == 64 ? 2 : 3) : ((int)keyData[index + 2] == 128 ? 3 : 4));byte[] pemExponent1 = (keySize1024 ? new byte[64] : new byte[128]);

Array.Copy(keyData, index, pemExponent1,0, pemExponent1.Length);

index+=pemExponent1.Length;

index+= (keySize1024 ? ((int)keyData[index + 1] == 64 ? 2 : 3) : ((int)keyData[index + 2] == 128 ? 3 : 4));byte[] pemExponent2 = (keySize1024 ? new byte[64] : new byte[128]);

Array.Copy(keyData, index, pemExponent2,0, pemExponent2.Length);

index+=pemExponent2.Length;

index+= (keySize1024 ? ((int)keyData[index + 1] == 64 ? 2 : 3) : ((int)keyData[index + 2] == 128 ? 3 : 4));byte[] pemCoefficient = (keySize1024 ? new byte[64] : new byte[128]);

Array.Copy(keyData, index, pemCoefficient,0, pemCoefficient.Length);

RSAParameters para= newRSAParameters();

para.Modulus=pemModulus;

para.Exponent=pemPublicExponent;

para.D=pemPrivateExponent;

para.P=pemPrime1;

para.Q=pemPrime2;

para.DP=pemExponent1;

para.DQ=pemExponent2;

para.InverseQ=pemCoefficient;returnpara;

}#endregion

//extract valid content from PEM file

public static string extractFromPemFile(stringfilePath)

{string result = "";string COMMENT_BEGIN_FLAG = "-----";//=============//从头到尾以流的方式读出文本文件, 该方法会一行一行读出文本

using (System.IO.StreamReader sr = newSystem.IO.StreamReader(filePath, Encoding.UTF8))

{stringstr;

StringBuilder sb= newStringBuilder();while ((str = sr.ReadLine()) != null)

{if (!str.StartsWith(COMMENT_BEGIN_FLAG))

{

sb.Append(str);

}

}

result=sb.ToString();

}returnresult;

}//extract valid content from PEM format string

public static string extractFromPemFormat(stringinput)

{string result = "";string COMMENT_BEGIN_FLAG = "-----";string[] splitFlagArray = { "\r", "\n"};string[] itemArray =input.Split(splitFlagArray, StringSplitOptions.RemoveEmptyEntries);

StringBuilder sb= newStringBuilder();foreach (string item initemArray)

{if (!item.StartsWith(COMMENT_BEGIN_FLAG))

{

sb.Append(item);

}

}

result=sb.ToString();returnresult;

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值