之前写过C#与JAVA语言RSA算法的互通程序,后来又找了找JAVA与GO语言互通的RSA算法,发现没有现成的,经过探索后,成功实现了两者的互通,现在分享如下:
注意:1 .两者的公钥和私钥是不能混用的,即JAVA的公私钥是不能直接用于GO的,反过来也不行。
2.下面的JAVA源码的解密思想是:
(1)将java产生的公钥pubKey_from_java复制给Go
(2)Go利用java的公钥加密一段信息,data,err=RsaEncrypt(" hello ",pubKey_from_java)
(3)java利用自己的私钥privKey_from_java解密这段信息data,已验证通过。
3. Go源码解密的思想与上述同理,不再赘述。直接上源代码。
JAVA实现RSA的源码如下:
package rsa;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
public class RSAHelper {
/**
*私有数据成员,主要是公钥和私钥
*由程序自己产生,公钥需传递给通信另一方
*/
private static String publicKey;
private static String privateKey;
/**
* 产生公钥和私钥
*/
private static void genKeys() throws Exception{
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
//密钥位数
keyPairGen.initialize(1024);
//密钥对
KeyPair keyPair = keyPairGen.generateKeyPair();
// 公钥
PublicKey pubKey = (RSAPublicKey) keyPair.getPublic();
// 私钥
PrivateKey privKey = (RSAPrivateKey) keyPair.getPrivate();
publicKey= getKeyString(pubKey);
privateKey= getKeyString(privKey);
}
/**
*获取程序自动生成的公钥
* @return 返回公钥
*/
public static String getPubKey()
{
return publicKey;
}
/**
*获取程序自动生成的私钥
* @return 返回私钥
*/
public static String getPrivKey()
{
return privateKey;
}
/**
* 得到公钥
* @param key 密钥字符串(经过base64编码)
* @throws Exception
*/
public static PublicKey getPublicKey(String key) throws Exception {
byte[] keyBytes;
keyBytes = (new BASE64Decoder()).decodeBuffer(key);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(keySpec);
return publicKey;
}
/**
* 得到私钥
* @param key 密钥字符串(经过base64编码)
* @throws Exception
*/
public static PrivateKey getPrivateKey(String key) throws Exception {
byte[] keyBytes;
keyBytes = (new BASE64Decoder()).decodeBuffer(key);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
}
/**
* 得到密钥字符串(经过base64编码)
* @return
*/
public static String getKeyString(Key key) throws Exception {
byte[] keyBytes = key.getEncoded();
String s = (new BASE64Encoder()).encode(keyBytes);
return s;
}
/**
*利用Go语言产生的公钥加密
* @param pubkey_from_go 从服务器(go语言实现)获取的公钥
* @param plainText 需要加密的字符串
*/
public static String encByGoPubKey(String pubkey_from_go,String plainText) throws Exception {
//加解密类
Cipher cipher = Cipher.getInstance("RSA");//Cipher.getInstance("RSA/ECB/PKCS1Padding");
byte[] plainTextBytes = plainText.getBytes();
//用Go语言产生的公钥加密
PublicKey pubkey_go=getPublicKey(pubkey_from_go);
cipher.init(Cipher.ENCRYPT_MODE, pubkey_go);
byte[] enBytes = cipher.doFinal(plainTextBytes);
String encryptString = (new BASE64Encoder()).encode(enBytes);
return encryptString;
}
/**
*用私钥解密Go语言用java公钥产生的密文
*
*/
public static String decryptByJavaPrivKey(String privkey_from_java,String encryptedString) throws Exception{
//加解密类
Cipher cipher = Cipher.getInstance("RSA");//Cipher.getInstance("RSA/ECB/PKCS1Padding");
// G0语言通过java产生的公钥加密得到的加密后的字符串
byte[] enBytes=(new BASE64Decoder()).decodeBuffer(encryptedString);
//通过密钥字符串得到密钥
PrivateKey privateKey = getPrivateKey(privkey_from_java);
//解密
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[]deBytes = cipher.doFinal(enBytes);
String decryptString=new String(deBytes);
return decryptString;
}
public static void main(String[] args) throws Exception {
genKeys();
String publicKeyString =getPubKey();
System.out.println("public key:\n" + publicKeyString);
String privateKeyString = getPrivKey();
System.out.println("private key:\n" + privateKeyString);
//java生成的公钥和私钥
String pubKey_from_java="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDmb2bXhcfeiosnxs0bD17isalelyS2/0xKQdJU"+
"VUyMdt+/5Inm/S5upDFrliMs3i9zj3PtJWO7yzRfiBnoDNlOfTqPNY6DI9FXnhDgjQMJhp1Zbhl7"+
"d74E63CBVTU6Deocqfy/KCiPjQnpTzln89Mm7eE3WbvlmvX3mO7uD2/geQIDAQAB";
String privKey_from_java="MIIBNwIBADANBgkqhkiG9w0BAQEFAASCASEwggEdAgEAAoGBAOZvZteFx96KiyfGz"+
"RsPXuKxqV6XJLb/TEpB0lRVTIx237/kieb9Lm6kMWuWIyzeL3OPc+0lY7vLNF+IGe"+
"gM2U59Oo81joMj0VeeEOCNAwmGnVluGXt3vgTrcIFVNToN6hyp/L8oKI+NCelPOWf"+
"z0ybt4TdZu+Wa9feY7u4Pb+B5AgEAAoGBAL5mmBxGzwIDib2hF0JfrfA0ChU9X7nR"+
"MrE8t9S08l4xrul4pbV1x1LmWmtiD8h4Ac9DXe858LFv0uOIqpdBXp9ZMyoqBC97L"+
"wDboutzt6OcXQ3hMVTOszn9cFFIf6JXaLz8HgocqAHTLVM4LwmyZNbGAyX/vja9BX"+
"jVtUQdVxt9AgEAAgEAAgEAAgEAAgEA";
//Go生成的公钥和私钥
String pubKey_from_go="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZsfv1qscqYdy4vY+P4e3cAtmv"+
"ppXQcRvrF1cB4drkv0haU24Y7m5qYtT52Kr539RdbKKdLAM6s20lWy7+5C0Dgacd"+
"wYWd/7PeCELyEipZJL07Vro7Ate8Bfjya+wltGK9+XNUIHiumUKULW4KDx21+1NL"+
"AUeJ6PeW+DAkmJWF6QIDAQAB";
String privKey_from_go="MIICXQIBAAKBgQDZsfv1qscqYdy4vY+P4e3cAtmvppXQcRvrF1cB4drkv0haU24Y"+
"7m5qYtT52Kr539RdbKKdLAM6s20lWy7+5C0DgacdwYWd/7PeCELyEipZJL07Vro7"+
"Ate8Bfjya+wltGK9+XNUIHiumUKULW4KDx21+1NLAUeJ6PeW+DAkmJWF6QIDAQAB"+
"AoGBAJlNxenTQj6OfCl9FMR2jlMJjtMrtQT9InQEE7m3m7bLHeC+MCJOhmNVBjaM"+
"ZpthDORdxIZ6oCuOf6Z2+Dl35lntGFh5J7S34UP2BWzF1IyyQfySCNexGNHKT1G1"+
"XKQtHmtc2gWWthEg+S6ciIyw2IGrrP2Rke81vYHExPrexf0hAkEA9Izb0MiYsMCB"+
"/jemLJB0Lb3Y/B8xjGjQFFBQT7bmwBVjvZWZVpnMnXi9sWGdgUpxsCuAIROXjZ40"+
"IRZ2C9EouwJBAOPjPvV8Sgw4vaseOqlJvSq/C/pIFx6RVznDGlc8bRg7SgTPpjHG"+
"4G+M3mVgpCX1a/EU1mB+fhiJ2LAZ/pTtY6sCQGaW9NwIWu3DRIVGCSMm0mYh/3X9"+
"DAcwLSJoctiODQ1Fq9rreDE5QfpJnaJdJfsIJNtX1F+L3YceeBXtW0Ynz2MCQBI8"+
"9KP274Is5FkWkUFNKnuKUK4WKOuEXEO+LpR+vIhs7k6WQ8nGDd4/mujoJBr5mkrw"+
"DPwqA3N5TMNDQVGv8gMCQQCaKGJgWYgvo3/milFfImbp+m7/Y3vCptarldXrYQWO"+
"AQjxwc71ZGBFDITYvdgJM1MTqc8xQek1FXn1vfpy2c6O";
//用Go语言产生的公钥加密
String plainText = "Hello,I am plaintext string!@sina.com";
String encryptString=encByGoPubKey(pubKey_from_go,plainText);
System.out.println("加密后的字符串:\n"+encryptString);
//解密G0语言通过java公钥加密得到的字符串
String enString_from_go="jIYRVYv3kDiSXN6fWMuZdJj/ljLUv51TtNbbZi1m8h2jc/UzYxVnuYUp66kd8dEeROQ0gAqwXdovBFauzoDfPUtCBWZ0OJZrnyOC1jlE0/FRTIq+goA7B97k2WdYueEtkydNsahNzsABO+mA/hZE+P+oiZojoZISpAVyWyVD7XA=";
String decryptString=decryptByJavaPrivKey(privKey_from_java,enString_from_go);
System.out.println("解密后的字符串:\n"+decryptString);
}
}
说明:
1. 上述java代码的注释已经比较完善,写过加密的童鞋应该都能看懂。其中引入的两个包:
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
Eclipse默认情况下是不支持的Base64编码的,设置方法:
右键项目->属性->java build path->Libraries->jre SystemLibrary->Access rules,在出现的对话框中,第一行Resolution选择accessiable,第二行填上:** 即可 (两个星号)。
接下来是GO语言的源代码
package main import ( "crypto/rand" "crypto/rsa" "crypto/x509" "encoding/base64" "encoding/pem" "errors" "flag" "fmt" ) var decrypted string func init() { flag.StringVar(&decrypted, "d", "", "加密过的数据") flag.Parse() } func main() { var data []byte var err error if decrypted != "" { data, err = base64.StdEncoding.DecodeString(decrypted) if err != nil { panic(err) } } else { //利用客户端传来的公钥加密有效信息 data, err = RsaEncrypt([]byte("polaris@studygolang.com"), publicKey_by_java) if err != nil { panic(err) } fmt.Println("rsa encrypt(base64): \n" + base64.StdEncoding.EncodeToString(data)) } data, err = base64.StdEncoding.DecodeString("W/lT8KrQLB7Pj3sXI0sAwCyFjvCnVr/tUlgYHqUx3L8dZ5+sYMJqtatsas3Ks5qVmdMFBIKg4tZiA0WsqOQgt36z/xudRBvHxLIFSowpO4xjcym4vBaWnUiYEzJDed7jbSwaPHQTSLinqclSxbh32TKTJ9dFmihD2/vp0bfyt/k=") origData, err := RsaDecrypt(data, privateKey) if err != nil { panic(err) } fmt.Println("rsa decrypt(base64):\n" + string(origData)) } // 公钥和私钥可以从文件中读取 var privateKey = []byte(` -----BEGIN RSA PRIVATE KEY----- MIICXQIBAAKBgQDZsfv1qscqYdy4vY+P4e3cAtmvppXQcRvrF1cB4drkv0haU24Y 7m5qYtT52Kr539RdbKKdLAM6s20lWy7+5C0DgacdwYWd/7PeCELyEipZJL07Vro7 Ate8Bfjya+wltGK9+XNUIHiumUKULW4KDx21+1NLAUeJ6PeW+DAkmJWF6QIDAQAB AoGBAJlNxenTQj6OfCl9FMR2jlMJjtMrtQT9InQEE7m3m7bLHeC+MCJOhmNVBjaM ZpthDORdxIZ6oCuOf6Z2+Dl35lntGFh5J7S34UP2BWzF1IyyQfySCNexGNHKT1G1 XKQtHmtc2gWWthEg+S6ciIyw2IGrrP2Rke81vYHExPrexf0hAkEA9Izb0MiYsMCB /jemLJB0Lb3Y/B8xjGjQFFBQT7bmwBVjvZWZVpnMnXi9sWGdgUpxsCuAIROXjZ40 IRZ2C9EouwJBAOPjPvV8Sgw4vaseOqlJvSq/C/pIFx6RVznDGlc8bRg7SgTPpjHG 4G+M3mVgpCX1a/EU1mB+fhiJ2LAZ/pTtY6sCQGaW9NwIWu3DRIVGCSMm0mYh/3X9 DAcwLSJoctiODQ1Fq9rreDE5QfpJnaJdJfsIJNtX1F+L3YceeBXtW0Ynz2MCQBI8 9KP274Is5FkWkUFNKnuKUK4WKOuEXEO+LpR+vIhs7k6WQ8nGDd4/mujoJBr5mkrw DPwqA3N5TMNDQVGv8gMCQQCaKGJgWYgvo3/milFfImbp+m7/Y3vCptarldXrYQWO AQjxwc71ZGBFDITYvdgJM1MTqc8xQek1FXn1vfpy2c6O -----END RSA PRIVATE KEY----- `) /**/ var privateKey_by_java = []byte(` -----BEGIN RSA PRIVATE KEY----- MIIBNwIBADANBgkqhkiG9w0BAQEFAASCASEwggEdAgEAAoGBAOZvZteFx96KiyfGz RsPXuKxqV6XJLb/TEpB0lRVTIx237/kieb9Lm6kMWuWIyzeL3OPc+0lY7vLNF+IGe gM2U59Oo81joMj0VeeEOCNAwmGnVluGXt3vgTrcIFVNToN6hyp/L8oKI+NCelPOWf z0ybt4TdZu+Wa9feY7u4Pb+B5AgEAAoGBAL5mmBxGzwIDib2hF0JfrfA0ChU9X7nR MrE8t9S08l4xrul4pbV1x1LmWmtiD8h4Ac9DXe858LFv0uOIqpdBXp9ZMyoqBC97L wDboutzt6OcXQ3hMVTOszn9cFFIf6JXaLz8HgocqAHTLVM4LwmyZNbGAyX/vja9BX jVtUQdVxt9AgEAAgEAAgEAAgEAAgEA -----END RSA PRIVATE KEY----- `) var publicKey = []byte(` -----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZsfv1qscqYdy4vY+P4e3cAtmv ppXQcRvrF1cB4drkv0haU24Y7m5qYtT52Kr539RdbKKdLAM6s20lWy7+5C0Dgacd wYWd/7PeCELyEipZJL07Vro7Ate8Bfjya+wltGK9+XNUIHiumUKULW4KDx21+1NL AUeJ6PeW+DAkmJWF6QIDAQAB -----END PUBLIC KEY----- `) var publicKey_by_java = []byte(` -----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDmb2bXhcfeiosnxs0bD17isalel yS2/0xKQdJUVUyMdt+/5Inm/S5upDFrliMs3i9zj3PtJWO7yzRfiBnoDNlOfTqPNY 6DI9FXnhDgjQMJhp1Zbhl7d74E63CBVTU6Deocqfy/KCiPjQnpTzln89Mm7eE3Wbv lmvX3mO7uD2/geQIDAQAB -----END PUBLIC KEY----- `) //利用客户端传来的公钥(java语言产生)加密 func RsaEncrypt(origData []byte, pubKey []byte) ([]byte, error) { block, _ := pem.Decode(pubKey) if block == nil { return nil, errors.New("public key error") } pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes) if err != nil { return nil, err } pub := pubInterface.(*rsa.PublicKey) return rsa.EncryptPKCS1v15(rand.Reader, pub, origData) } // 解密由客户端(java)利用服务器(Go语言实现,即本程序)公钥加密的信息 func RsaDecrypt(ciphertext []byte, privKey []byte) ([]byte, error) { block, _ := pem.Decode(privKey) if block == nil { return nil, errors.New("private key error!") } priv, err := x509.ParsePKCS1PrivateKey(block.Bytes) if err != nil { return nil, err } return rsa.DecryptPKCS1v15(rand.Reader, priv, ciphertext) }
说明:更多关于Go语言的RSA加密算法的解析请参考:http://blog.studygolang.com/?p=137