JAVA与GO语言实现的RSA加密算法的互通

igoqhb · · 6006 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

之前写过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



有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:igoqhb

查看原文:JAVA与GO语言实现的RSA加密算法的互通

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

6006 次点击  
加入收藏 微博
1 回复  |  直到 2000-01-01 00:00:00
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传