java rsa .net_.NET和java的RSA互通,僅此而已 | 學步園

.NET和java的RSA互通,僅此而已

在開始這篇文章之前,先請讀者朋友閱讀老唐的這兩篇文章:

和我的這篇文章

前面老唐的兩篇文章中提到,要想實現.NET和Java的RSA互通,只能拋棄.NET現有的加密項目中的BigInteger類(.NET Framework4中已增加了這個類的實現,在System.Numberic命名空間中),這個BigInteger類實際上就是仿照着java的BigInteger類來寫的。

利用這個類的確可以很好的實現RSA的加解密,比如,在.NET端,構建一個公鑰對應的BigIntegere、一個模對應的BigInteger n和一個明文對應的BigIntegerm,然後執行語句BigInteger c=m.modPow(e,n),便可以實現加密操作,密文為c,這樣的加密是標準加密,沒有附加任何填充算法的加密。

老唐的文章中說,不能互通是因為加密標準不一樣,導致一方加密而另一方不能解密,其實不然,.NET採用的加密標準是PKCS1Padding(或OAEPPadding——只支持XP以上版本),這也是我在中提到的一種填充算法,而java同樣支持這一填充標準,既然可以遵循統一的標準,那麼.NET和java的RSA互通,無需添加任何新代碼便可以輕鬆實現!

請看下面的示例(.NET端加密,Java端解密):

Java端代碼:

import java.math.BigInteger;

import java.util.Scanner;

import java.security.KeyFactory;

import java.security.PrivateKey;

import java.security.KeyPair;

import java.security.KeyPairGenerator;

import java.security.PublicKey;

import java.security.interfaces.RSAPrivateKey;

import java.security.interfaces.RSAPublicKey;

import java.security.spec.RSAPublicKeySpec;

import javax.crypto.Cipher;

import sun.misc.*;

public class RsaKey {

public static void main(String[] args) throws Exception {

//生成公私鑰對

KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");

keyPairGen.initialize(1024);

KeyPair keyPair = keyPairGen.generateKeyPair();

PublicKey publicKey = (RSAPublicKey) keyPair.getPublic();

PrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

//將公鑰和模進行Base64編碼

KeyFactory keyFactory = KeyFactory.getInstance("RSA");

RSAPublicKeySpec publicSpec= keyFactory.getKeySpec(publicKey,RSAPublicKeySpec.class);

BigInteger modulus = publicSpec.getModulus();

BigInteger exponent=publicSpec.getPublicExponent();

byte[] ary_m=modulus.toByteArray();//注意:對公鑰和模進行Base64編碼時,不是對BigInteger對應的字符串編碼,而是對其內部 的字節數組進行編碼

byte[] ary_e=exponent.toByteArray();

String str_m;

String str_e;

if(ary_m[0]==0 && ary_m.length==129)//判斷數組首元素是否為0,若是,則將其刪除,保證模的位數是128

{

byte[] temp=new byte[ary_m.length-1];

for(int i=1;i

{

temp[i-1]=ary_m[i];

}

str_m=(new BASE64Encoder()).encodeBuffer(temp);

}

else

{

str_m=(new BASE64Encoder()).encodeBuffer(ary_m);

}

str_e=(new BASE64Encoder()).encodeBuffer(ary_e);

System.out.println("公鑰為:"+str_e);

System.out.println("模為:"+str_m);

System.out.println("運行.NET程序,用所提供的公鑰和模進行加密,然後將加密結果輸入本程序進行解密:");

Scanner sc=new Scanner(System.in);

String str_en="";

String st="";

while(!(st=sc.nextLine()).equals(""))

{

str_en+=st;

}

byte[] ary_en=(new BASE64Decoder()).decodeBuffer(str_en);

//解密

//注意Cipher初始化時的參數“RSA/ECB/PKCS1Padding”,代表和.NET用相同的填充算法,如果是標準RSA加密,則參數為“RSA”

Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

cipher.init(Cipher.DECRYPT_MODE, privateKey);

byte[] deBytes = cipher.doFinal(ary_en);

String s = new String(deBytes );

System.out.println("解密結果為:" + s);

}

}

Java端演示截圖

0_12996385313ZDV.gif

.NET端代碼:

static void Main(string[] args)

{

try

{

RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();

RSAParameters para = new RSAParameters();

//加密

Console.WriteLine("請輸入公鑰");

string publicKey = Console.ReadLine();

Console.WriteLine("請輸入模:");

string modulus = Console.ReadLine();

while(true)

{

string s = Console.ReadLine();

if (s == "")

{

break;

}

else

{

modulus += s;

}

}

Console.WriteLine("請輸入明文:");

string m = Console.ReadLine();

para.Exponent = Convert.FromBase64String(publicKey);

para.Modulus = Convert.FromBase64String(modulus);

rsa.ImportParameters(para);

byte[] enBytes = rsa.Encrypt(UTF8Encoding.UTF8.GetBytes(m),false);

Console.WriteLine("密文為:"+Convert.ToBase64String(enBytes));

Console.ReadLine();

}

catch(Exception ex)

{

Console.WriteLine(ex.Message);

Console.ReadLine();

}

}

.NET端演示截圖:

0_1299638852qqBo.gif

接下來的示例是(java端加密,.NET端解密):

.net端代碼:

static void Main(string[] args)

{

try

{

RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();

RSAParameters para = rsa.ExportParameters(true);

//加¨®密¨¹

Console.WriteLine("公?鑰?為a:êo"+ Convert.ToBase64String(para.Exponent));

Console.WriteLine("模¡ê為a:êo" + Convert.ToBase64String(para.Modulus));

Console.WriteLine("請?輸º?入¨?密¨¹文?");

string enStr = Console.ReadLine();

while(true)

{

string s = Console.ReadLine();

if (s == "")

{

break;

}

else

{

enStr += s;

}

}

byte[] deBytes = rsa.Decrypt(Convert.FromBase64String(enStr),false);

Console.WriteLine("明¡Â文?為a:êo"+UTF8Encoding.UTF8.GetString(deBytes));

Console.ReadLine();

}

catch(Exception ex)

{

Console.WriteLine(ex.Message);

Console.ReadLine();

}

}

Java端代碼:

public static void main(String[] args) throws Exception {

Scanner sc=new Scanner(System.in);

//獲取公鑰、模及明文的字符串

System.out.println("請輸入公鑰:");

String str_exponent=sc.nextLine();

System.out.println("請輸入模:");

String str_modulus="";

String st="";

while(!(st=sc.nextLine()).equals(""))

{

str_modulus+=st;

}

System.out.println("請輸入明文:");

String str_m=sc.nextLine();

//創建公鑰

byte[] ary_exponent=(new BASE64Decoder()).decodeBuffer(str_exponent);

byte[] ary_modulus=(new BASE64Decoder()).decodeBuffer(str_modulus);

//注意構造函數,調用時指明正負值,1代表正值,否則報錯

BigInteger big_exponent = new BigInteger(1,ary_exponent);

BigInteger big_modulus = new BigInteger(1,ary_modulus);

RSAPublicKeySpec keyspec=new RSAPublicKeySpec(big_modulus,big_exponent);

KeyFactory keyfac=KeyFactory.getInstance("RSA");

PublicKey publicKey=keyfac.generatePublic(keyspec);

//進行加密

Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

cipher.init(Cipher.ENCRYPT_MODE, publicKey);

byte[] enBytes = cipher.doFinal(str_m.getBytes());

String s = (new BASE64Encoder()).encodeBuffer(enBytes);

System.out.println("加密結果為:" + s);

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java.NET中,RSA密钥的存储格式不同,因此需要进行格式转换才能实现密钥的交换。下面是Java.NET之间RSA密钥格式转换的详细步骤。 1. 将Java中的公钥格式转换为.NET中的公钥格式: Java中的公钥格式为X.509证书格式,需要将其转换为XML格式。具体步骤如下: ``` KeyFactory keyFactory = KeyFactory.getInstance("RSA"); X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes); PublicKey publicKey = keyFactory.generatePublic(publicKeySpec); StringWriter sw = new StringWriter(); XmlWriter xw = XmlWriter.Create(sw); RSAParameters parameters = new RSAParameters(); parameters.Modulus = publicKey.getModulus().toByteArray(); parameters.Exponent = publicKey.getPublicExponent().toByteArray(); xw.WriteStartElement("RSAKeyValue"); xw.WriteElementString("Modulus", Convert.ToBase64String(parameters.Modulus)); xw.WriteElementString("Exponent", Convert.ToBase64String(parameters.Exponent)); xw.WriteEndElement(); xw.Flush(); ``` 2. 将Java中的私钥格式转换为.NET中的私钥格式: Java中的私钥格式为PKCS#8格式,需要将其转换为XML格式。具体步骤如下: ``` KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes); PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec); StringWriter sw = new StringWriter(); XmlWriter xw = XmlWriter.Create(sw); RSAParameters parameters = new RSAParameters(); parameters.Modulus = privateKey.getModulus().toByteArray(); parameters.D = privateKey.getPrivateExponent().toByteArray(); parameters.P = privateKey instanceof RSAPrivateCrtKey ? ((RSAPrivateCrtKey)privateKey).getPrimeP().toByteArray() : null; parameters.Q = privateKey instanceof RSAPrivateCrtKey ? ((RSAPrivateCrtKey)privateKey).getPrimeQ().toByteArray() : null; parameters.DP = privateKey instanceof RSAPrivateCrtKey ? ((RSAPrivateCrtKey)privateKey).getPrimeExponentP().toByteArray() : null; parameters.DQ = privateKey instanceof RSAPrivateCrtKey ? ((RSAPrivateCrtKey)privateKey).getPrimeExponentQ().toByteArray() : null; parameters.InverseQ = privateKey instanceof RSAPrivateCrtKey ? ((RSAPrivateCrtKey)privateKey).getCrtCoefficient().toByteArray() : null; xw.WriteStartElement("RSAKeyValue"); xw.WriteElementString("Modulus", Convert.ToBase64String(parameters.Modulus)); xw.WriteElementString("Exponent", Convert.ToBase64String(privateKey.getPublicExponent().toByteArray())); xw.WriteElementString("D", Convert.ToBase64String(parameters.D)); xw.WriteElementString("P", Convert.ToBase64String(parameters.P)); xw.WriteElementString("Q", Convert.ToBase64String(parameters.Q)); xw.WriteElementString("DP", Convert.ToBase64String(parameters.DP)); xw.WriteElementString("DQ", Convert.ToBase64String(parameters.DQ)); xw.WriteElementString("InverseQ", Convert.ToBase64String(parameters.InverseQ)); xw.WriteEndElement(); xw.Flush(); ``` 3. 将.NET中的公钥格式转换为Java中的公钥格式: .NET中的公钥格式为XML格式,需要将其转换为X.509证书格式。具体步骤如下: ``` XmlDocument doc = new XmlDocument(); doc.LoadXml(xmlPublicKey); RSAParameters parameters = new RSAParameters(); parameters.Modulus = Convert.FromBase64String(doc.SelectSingleNode("//Modulus").InnerText); parameters.Exponent = Convert.FromBase64String(doc.SelectSingleNode("//Exponent").InnerText); RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); rsa.ImportParameters(parameters); RSACryptoServiceProvider rsaPublic = new RSACryptoServiceProvider(); rsaPublic.ImportParameters(rsa.ExportParameters(false)); byte[] x509publicKey = rsaPublic.ExportCspBlob(false); ``` 4. 将.NET中的私钥格式转换为Java中的私钥格式: .NET中的私钥格式为XML格式,需要将其转换为PKCS#8格式。具体步骤如下: ``` XmlDocument doc = new XmlDocument(); doc.LoadXml(xmlPrivateKey); RSAParameters parameters = new RSAParameters(); parameters.Modulus = Convert.FromBase64String(doc.SelectSingleNode("//Modulus").InnerText); parameters.D = Convert.FromBase64String(doc.SelectSingleNode("//D").InnerText); parameters.P = Convert.FromBase64String(doc.SelectSingleNode("//P").InnerText); parameters.Q = Convert.FromBase64String(doc.SelectSingleNode("//Q").InnerText); parameters.DP = Convert.FromBase64String(doc.SelectSingleNode("//DP").InnerText); parameters.DQ = Convert.FromBase64String(doc.SelectSingleNode("//DQ").InnerText); parameters.InverseQ = Convert.FromBase64String(doc.SelectSingleNode("//InverseQ").InnerText); RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); rsa.ImportParameters(parameters); byte[] pkcs8privateKey = rsa.ExportPkcs8PrivateKey(); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值