【加密算法】RSA(c#、java、php互通)
本文为转载文章,原文地址:http://www.cnblogs.com/FoChen/p/4740814.html。
一、摘要
在数据安全上rsa起着非常大的作用,特别是数据网络通讯的安全上。当异构系统在数据网络通讯上对安全性有所要求时,rsa将作为其中的一种选择,此时rsa的互通性就显得尤为重要了。
本文参考网络资料,提供了rsa互通性的一种可行的解决方案(c#,java,php),而这种互通性是在一定的局限性上达成的,比如密钥是1024位的(更高位没试过,应该也可行),基于PKCS1填充方式。
所编写的代码有一部分使用了硬编码,同时注重了功能的实现,在类结构设计上关注不多,有需要的可自行修改重构。
二、生成互通密钥对
重点参考了Jeffrey Walton(http://www.codeproject.com/Articles/25487/Cryptographic-Interoperability-Keys)
1、C#
//生成公私钥对 默认xml格式 KeyPair keyPair = KeyGenerator.GenerateKeyPair(); //转换成不同的格式 KeyPair asnKeyPair = keyPair.ToASNKeyPair(); //ASN格式 java平台惯用 KeyPair xmlKeyPair = keyPair.ToXMLKeyPair(); //XML格式 c#平台惯用 KeyPair pemKeyPair = keyPair.ToPEMKeyPair(); //PEM格式 php平台惯用 PEM格式的密钥格式是PKCS#8 Console.WriteLine("ASN格式"); Console.WriteLine(asnKeyPair.PublicKey); Console.WriteLine(asnKeyPair.PrivateKey); Console.WriteLine(""); Console.WriteLine("XML格式"); Console.WriteLine(xmlKeyPair.PublicKey); Console.WriteLine(xmlKeyPair.PrivateKey); Console.WriteLine(""); Console.WriteLine("PEM格式"); Console.WriteLine(pemKeyPair.PublicKey); Console.WriteLine(pemKeyPair.PrivateKey);
2、JAVA
import cn.ubingo.security.rsa.core.*; import cn.ubingo.security.rsa.key.*; //生成密钥对 KeyPair keyPair = KeyGenerator.generateKeyPair(); //转换成不同的格式 KeyPair asnKeyPair = keyPair.toASNKeyPair(); KeyPair xmlKeyPair = asnKeyPair.toXMLKeyPair(); KeyPair pemKeyPair = xmlKeyPair.toPEMKeyPair(); //获取公私钥,以asn格式的为例 String publicKey = asnKeyPair.getPublicKey(); String privateKey = asnKeyPair.getPrivateKey();
C#密钥生成结果(推荐使用PEM格式的密钥)
三、加密解密
基于三种语言环境都支持的RSA PKCS1填充方式的算法,实现加解密互通
KeyWorker的c#:Encrypt,Decrypt或java:encrypt,decrypt或php:encrypt,decrypt方法实现加解密的功能
1、C#代码
//ASN var publicWorker = new KeyWorker(asnKeyPair.PublicKey, KeyFormat.ASN); //公钥加密器 var privateWorker = new KeyWorker(asnKeyPair.PrivateKey, KeyFormat.ASN); //私钥解密器 //XML //var publicWorker = new KeyWorker(xmlKeyPair.PublicKey, KeyFormat.XML); //公钥加密器 //var privateWorker = new KeyWorker(xmlKeyPair.PrivateKey, KeyFormat.XML); //私钥解密器 //PEM //var publicWorker = new KeyWorker(pemKeyPair.PublicKey, KeyFormat.PEM); //公钥加密器 //var privateWorker = new KeyWorker(pemKeyPair.PrivateKey, KeyFormat.PEM); //私钥解密器 string plaintext = "你好!世界"; //加密 string ciphertext = publicWorker.Encrypt(plaintext); Console.WriteLine(ciphertext); //解密 string newPlaintext = privateWorker.Decrypt(ciphertext); Console.WriteLine(newPlaintext);
2、JAVA
import cn.ubingo.security.rsa.core.*; import cn.ubingo.security.rsa.data.*; //ASN KeyWorker privateWorker = new KeyWorker(privateKey, KeyFormat.ASN); KeyWorker publicWorker = new KeyWorker(publicKey, KeyFormat.ASN); System.out.print(privateWorker.decrypt(publicWorker.encrypt("你好!世界"))); System.out.print(publicWorker.decrypt(privateWorker.encrypt("你好!中国"))); //XML privateWorker = new KeyWorker(xmlKeyPair.getPrivateKey(), KeyFormat.XML); publicWorker = new KeyWorker(xmlKeyPair.getPublicKey(), KeyFormat.XML); System.out.print(privateWorker.decrypt(publicWorker.encrypt("你好!世界"))); System.out.print(publicWorker.decrypt(privateWorker.encrypt("你好!中国"))); //PEM privateWorker = new KeyWorker(pemKeyPair.getPrivateKey(), KeyFormat.PEM); publicWorker = new KeyWorker(pemKeyPair.getPublicKey(), KeyFormat.PEM); System.out.print(privateWorker.decrypt(publicWorker.encrypt("你好!世界"))); System.out.print(publicWorker.decrypt(privateWorker.encrypt("你好!中国")));
3、PHP
请保证php文件为utf-8的格式
include "KeyWorker.php"; use Cn\Ubingo\Security\RSA\Core as core; use Cn\Ubingo\Security\RSA\Data as data; /*PEM TEST*/ $publicWorker = new data\KeyWorker("-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCZw5tyBNJsjgVrPkLUIWF9el5E OXL1AydVBnJ/WWPKTZJBWYxudW+1jI5ifML+1DkCxw/2QLowzViV1OLnpNAWr7zv LpN6i7OZtq0o2Yfc+vv6vCctTpMvFartRRwDeXTRBgoGd71UwWgdMOu8Gmr9sv5u 3C9Kj5fhj0I4WgB94wIDAQAB -----END PUBLIC KEY-----",core\KeyFormat::PEM); $privateWorker = new data\KeyWorker("-----BEGIN PRIVATE KEY----- MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJnDm3IE0myOBWs+ QtQhYX16XkQ5cvUDJ1UGcn9ZY8pNkkFZjG51b7WMjmJ8wv7UOQLHD/ZAujDNWJXU 4uek0BavvO8uk3qLs5m2rSjZh9z6+/q8Jy1Oky8Vqu1FHAN5dNEGCgZ3vVTBaB0w 67waav2y/m7cL0qPl+GPQjhaAH3jAgMBAAECgYA6ANHYlv0RuhlNNTVcdCMkhE6f CdTVnBTwO/hhFcVRASYUxMT2vhIfuB/WAx5DpqbC53ib+hrCYhPyoVXe8AsWjgBJ cj3RHxjLMou0Jbu6mTjcLgKzMYM85yHscmmDcc8l/ep9BhbiJJsTVM8RqqXfdPmY 5CAgfwsNXruC7Zb5wQJBAMxVZhR+IzoeYLsmEciy2oOaTq5u8O6yjx7RapIggIKT dRU5G2GeCyLRHyZH/+U2/nL3undiP74fxizatzgTE3ECQQDApNKzaMobPW23wRes E+dDjJxYnqVqOmZS22D6s+BKwDmHpOt+oJmrirY4LWmOUwUfgAboDWH5y/q5+qJH P5STAkEAux+F4UR2nDXPnfPKG4L3K8f3QDUm/WGWQcHEF9gd9/Z0JaBrm+TxC8x4 +0S6ar4HHWASalwWRdWxVchiO770cQJAGaEUAxhq4wreIPdIffU77Em1tziMC0Dv whA7q77olSlTvg8b4YHeT+spaPnptCypXtJ6mL7HDSOtHLcSheYYjwJBAJFdK3vg ZS0Sk4oy6iOaOcux+5uBkpF9ran0GIpehyGzia+F1Xf/+NnS22qER/ADvRMNnyHf QH24qWxQuST39UQ = -----END PRIVATE KEY-----",core\KeyFormat::PEM); echo $publicWorker->decrypt($privateWorker->encrypt("你好!世界")); echo $privateWorker->decrypt($publicWorker->encrypt("你好!中国")); /*ASN TEST*/ $publicWorker = new data\KeyWorker("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCZw5tyBNJsjgVrPkLUIWF9el5EOXL1AydVBnJ/WWPKTZJBWYxudW+1jI5ifML+1DkCxw/2QLowzViV1OLnpNAWr7zvLpN6i7OZtq0o2Yfc+vv6vCctTpMvFartRRwDeXTRBgoGd71UwWgdMOu8Gmr9sv5u3C9Kj5fhj0I4WgB94wIDAQAB", core\KeyFormat::ASN); $privateWorker = new data\KeyWorker("MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJnDm3IE0myOBWs+QtQhYX16XkQ5cvUDJ1UGcn9ZY8pNkkFZjG51b7WMjmJ8wv7UOQLHD/ZAujDNWJXU4uek0BavvO8uk3qLs5m2rSjZh9z6+/q8Jy1Oky8Vqu1FHAN5dNEGCgZ3vVTBaB0w67waav2y/m7cL0qPl+GPQjhaAH3jAgMBAAECgYA6ANHYlv0RuhlNNTVcdCMkhE6fCdTVnBTwO/hhFcVRASYUxMT2vhIfuB/WAx5DpqbC53ib+hrCYhPyoVXe8AsWjgBJcj3RHxjLMou0Jbu6mTjcLgKzMYM85yHscmmDcc8l/ep9BhbiJJsTVM8RqqXfdPmY5CAgfwsNXruC7Zb5wQJBAMxVZhR+IzoeYLsmEciy2oOaTq5u8O6yjx7RapIggIKTdRU5G2GeCyLRHyZH/+U2/nL3undiP74fxizatzgTE3ECQQDApNKzaMobPW23wResE+dDjJxYnqVqOmZS22D6s+BKwDmHpOt+oJmrirY4LWmOUwUfgAboDWH5y/q5+qJHP5STAkEAux+F4UR2nDXPnfPKG4L3K8f3QDUm/WGWQcHEF9gd9/Z0JaBrm+TxC8x4+0S6ar4HHWASalwWRdWxVchiO770cQJAGaEUAxhq4wreIPdIffU77Em1tziMC0DvwhA7q77olSlTvg8b4YHeT+spaPnptCypXtJ6mL7HDSOtHLcSheYYjwJBAJFdK3vgZS0Sk4oy6iOaOcux+5uBkpF9ran0GIpehyGzia+F1Xf/+NnS22qER/ADvRMNnyHfQH24qWxQuST39UQ=", core\KeyFormat::ASN); echo $publicWorker->decrypt($privateWorker->encrypt("你好!世界")); echo $privateWorker->decrypt($publicWorker->encrypt("你好!中国"));
编译包:c#(4.0,dll) java(1.6,jar) php(5.3,php)
源代码:c#(4.0,visual studio 2012) java(1.6,eclipse 4.4.1) php(5.3,zend studio 12.0)
四、C#代码的简单封装类
/// <summary> /// RSA加密解密 /// 基于PKCS1填充 /// PEM密钥格式为PEM格式的密钥格式是PKCS#8 /// </summary> public class RsaHelper { /// <summary> /// 获取公私钥对 /// </summary> /// <param name="privateKey">私钥</param> /// <param name="publicKey">公钥</param> /// <param name="keyType">密钥格式</param> public static void GetKey(out string privateKey, out string publicKey, KeyType keyType = KeyType.PEM) { KeyFormat format = GetKeyFormat(keyType); KeyPair keyPair = KeyGenerator.GenerateKeyPair(format); privateKey = keyPair.PrivateKey; publicKey = keyPair.PublicKey; } /// <summary> /// 使用公钥加密 /// </summary> /// <param name="plaintext">明文</param> /// <param name="publicKey">公钥</param> /// <param name="keyType">密钥格式</param> /// <returns></returns> public static string Encrypt(string plaintext, string publicKey, KeyType keyType = KeyType.PEM) { KeyFormat format = GetKeyFormat(keyType); KeyWorker publicWorker = new KeyWorker(publicKey, format); return publicWorker.Encrypt(plaintext); } /// <summary> /// 使用私钥解密 /// </summary> /// <param name="ciphertext">密文</param> /// <param name="privateKey">私钥</param> /// <param name="keyType">密钥格式</param> /// <returns></returns> public static string Decrypt(string ciphertext, string privateKey, KeyType keyType = KeyType.PEM) { KeyFormat format = GetKeyFormat(keyType); KeyWorker privateWorker = new KeyWorker(privateKey, format); return privateWorker.Decrypt(ciphertext); } /// <summary> /// 返回密钥格式 /// </summary> /// <param name="keyType"></param> /// <returns></returns> private static KeyFormat GetKeyFormat(KeyType keyType) { switch (keyType) { case KeyType.ASN: return KeyFormat.ASN; case KeyType.XML: return KeyFormat.XML; case KeyType.PEM: return KeyFormat.PEM; default: throw new ArgumentException("无效参数keyType"); } } }