安全总是很重要的,各个语言对于通用的加密算法都会有实现。前段时间,用Go实现了RSA和DES的加密解密,在这分享一下。(对于RSA和DES加密算法本身,请查阅相关资料)
在PHP中,很多功能经常是一个函数解决;而Go中的却不是。本文会通过PHP加密,Go解密;Go加密,PHP解密来学习Go的RSA和DES相关的API。
该文讨论Go RSA加密解密。所有操作在linux下完成。
一、概要
这是一个非对称加密算法,一般通过公钥加密,私钥解密。
在加解密过程中,使用openssl生产密钥。执行如下操作:
1)创建私钥:
openssl genrsa -out private.pem 1024 //密钥长度,1024觉得不够安全的话可以用2048,但是代价也相应增大
2)创建公钥:
openssl rsa -in private.pem -pubout -out public.pem
这样便生产了密钥。
一般地,各个语言也会提供API,用于生成密钥。在Go中,可以查看encoding/pem包和crypto/x509包。具体怎么产生,可查看《GO加密解密RSA番外篇:生成RSA密钥》。
加密解密这块,涉及到很多标准,个人建议需要的时候临时学习一下。
二、Go RSA加密解密
1、rsa加解密,必然会去查crypto/ras这个包
Package rsa implements RSA encryption as specified in PKCS#1.
这是该包的说明:实现RSA加密技术,基于PKCS#1规范。
对于什么是PKCS#1,可以查阅相关资料。PKCS(公钥密码标准),而#1就是RSA的标准。可以查看:PKCS系列简介
从该包中函数的名称,可以看到有两对加解密的函数。
EncryptOAEP和DecryptOAEP
EncryptPKCS1v15和DecryptPKCS1v15
这称作加密方案,详细可以查看,PKCS #1 v2.1 RSA 算法标准
可见,当与其他语言交互时,需要确定好使用哪种方案。
PublicKey和PrivateKey两个类型分别代表公钥和私钥,关于这两个类型中成员该怎么设置,这涉及到RSA加密算法,本文中,这两个类型的实例通过解析文章开头生成的密钥得到。
2、解析密钥得到PublicKey和PrivateKey的实例
这个过程,我也是花了好些时间(主要对各种加密的各种东东不熟):怎么将openssl生成的密钥文件解析到公钥和私钥实例呢?
在encoding/pem包中,看到了—–BEGIN Type—–这样的字样,这正好和openssl生成的密钥形式差不多,那就试试。
在该包中,一个block代表的是PEM编码的结构,关于PEM,请查阅相关资料。我们要解析密钥,当然用Decode方法:
func Decode(data []byte) (p *Block, rest []byte)
这样便得到了一个Block的实例(指针)。
解析来看crypto/x509。为什么是x509呢?这又涉及到一堆概念。先不管这些,我也是看encoding和crypto这两个包的子包摸索出来的。
在x509包中,有一个函数:
func ParsePKIXPublicKey(derBytes []byte) (pub interface{}, err error)
从该函数的说明:ParsePKIXPublicKey parses a DER encoded public key. These values are typically found in PEM blocks with “BEGIN PUBLIC KEY”。可见这就是解析PublicKey的。另外,这里说到了PEM,可以上面的encoding/pem对了。(PKIX是啥东东,查看这里 )
而解析私钥的,有好几个方法,从上面的介绍,我们知道,RSA是PKCS#1,刚好有一个方法:
func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err error)
返回的就是rsa.PrivateKey。
3、解密解密实现
通过上面的介绍,Go中RSA的解密解密实现就不难了。代码如下:
2 |
func RsaEncrypt(origData []byte) ([]byte, error) { |
3 |
block, _ := pem.Decode(publicKey) |
5 |
return nil, errors.New( "public key error" ) |
7 |
pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes) |
11 |
pub := pubInterface.(*rsa.PublicKey) |
12 |
return rsa.EncryptPKCS1v15( rand .Reader, pub, origData) |
16 |
func RsaDecrypt(ciphertext []byte) ([]byte, error) { |
17 |
block, _ := pem.Decode(privateKey) |
19 |
return nil, errors.New( "private key error!" ) |
21 |
priv, err := x509.ParsePKCS1PrivateKey(block.Bytes) |
25 |
return rsa.DecryptPKCS1v15( rand .Reader, priv, ciphertext) |
其中,publicKey和privateKey是openssl生成的密钥,我生成的如下:
2 |
var privateKey = []byte(` |
3 |
-----BEGIN RSA PRIVATE KEY----- |
4 |
MIICXQIBAAKBgQDZsfv1qscqYdy4vY+P4e3cAtmvppXQcRvrF1cB4drkv0haU24Y |
5 |
7m5qYtT52Kr539RdbKKdLAM6s20lWy7+5C0DgacdwYWd/7PeCELyEipZJL07Vro7 |
6 |
Ate8Bfjya+wltGK9+XNUIHiumUKULW4KDx21+1NLAUeJ6PeW+DAkmJWF6QIDAQAB |
7 |
AoGBAJlNxenTQj6OfCl9FMR2jlMJjtMrtQT9InQEE7m3m7bLHeC+MCJOhmNVBjaM |
8 |
ZpthDORdxIZ6oCuOf6Z2+Dl35lntGFh5J7S34UP2BWzF1IyyQfySCNexGNHKT1G1 |
9 |
XKQtHmtc2gWWthEg+S6ciIyw2IGrrP2Rke81vYHExPrexf0hAkEA9Izb0MiYsMCB |
10 |
/jemLJB0Lb3Y/B8xjGjQFFBQT7bmwBVjvZWZVpnMnXi9sWGdgUpxsCuAIROXjZ40 |
11 |
IRZ2C9EouwJBAOPjPvV8Sgw4vaseOqlJvSq/C/pIFx6RVznDGlc8bRg7SgTPpjHG |
12 |
4G+M3mVgpCX1a/EU1mB+fhiJ2LAZ/pTtY6sCQGaW9NwIWu3DRIVGCSMm0mYh/3X9 |
13 |
DAcwLSJoctiODQ1Fq9rreDE5QfpJnaJdJfsIJNtX1F+L3YceeBXtW0Ynz2MCQBI8 |
14 |
9KP274Is5FkWkUFNKnuKUK4WKOuEXEO+LpR+vIhs7k6WQ8nGDd4/mujoJBr5mkrw |
15 |
DPwqA3N5TMNDQVGv8gMCQQCaKGJgWYgvo3/milFfImbp+m7/Y3vCptarldXrYQWO |
16 |
AQjxwc71ZGBFDITYvdgJM1MTqc8xQek1FXn1vfpy2c6O |
17 |
-----END RSA PRIVATE KEY----- |
20 |
var publicKey = []byte(` |
21 |
-----BEGIN PUBLIC KEY----- |
22 |
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZsfv1qscqYdy4vY+P4e3cAtmv |
23 |
ppXQcRvrF1cB4drkv0haU24Y7m5qYtT52Kr539RdbKKdLAM6s20lWy7+5C0Dgacd |
24 |
wYWd/7PeCELyEipZJL07Vro7Ate8Bfjya+wltGK9+XNUIHiumUKULW4KDx21+1NL |
25 |
AUeJ6PeW+DAkmJWF6QIDAQAB |
26 |
-----END PUBLIC KEY----- |
4、使用例子
8 |
data, err := RsaEncrypt([]byte( "polaris@studygolang.com" )) |
12 |
origData, err := RsaDecrypt(data) |
16 |
fmt.Println(string(origData)) |
该例子是加密完polaris@studygolang.com后立马解密
三、跨语言加解密
语言内部正常,还得看看和其他语言是否一致,即:其他语言加密,Go语言得正确解密;Go语言加密,其他语言正确解密
1、PHP RSA加解密
这里,我选择PHP,使用的是openssl扩展。PHP中加解密很简单,如下两个方法(这里只考虑用公钥加密,私钥解密):
bool openssl_public_encrypt ( string $data , string &$crypted , mixed $key [, int $padding = OPENSSL_PKCS1_PADDING ] )
bool openssl_private_decrypt ( string $data , string &$decrypted , mixed $key [, int $padding = OPENSSL_PKCS1_PADDING ] )
最后一个参数是加密方案(补齐方式)。由于Go中使用的是PKCS1而不是OAEP,所以,使用默认值即可。
PHP代码如下:
1 |
$privateKey = '-----BEGIN RSA PRIVATE KEY----- |
2 |
MIICXQIBAAKBgQDZsfv1qscqYdy4vY+P4e3cAtmvppXQcRvrF1cB4drkv0haU24Y |
3 |
7m5qYtT52Kr539RdbKKdLAM6s20lWy7+5C0DgacdwYWd/7PeCELyEipZJL07Vro7 |
4 |
Ate8Bfjya+wltGK9+XNUIHiumUKULW4KDx21+1NLAUeJ6PeW+DAkmJWF6QIDAQAB |
5 |
AoGBAJlNxenTQj6OfCl9FMR2jlMJjtMrtQT9InQEE7m3m7bLHeC+MCJOhmNVBjaM |
6 |
ZpthDORdxIZ6oCuOf6Z2+Dl35lntGFh5J7S34UP2BWzF1IyyQfySCNexGNHKT1G1 |
7 |
XKQtHmtc2gWWthEg+S6ciIyw2IGrrP2Rke81vYHExPrexf0hAkEA9Izb0MiYsMCB |
8 |
/jemLJB0Lb3Y/B8xjGjQFFBQT7bmwBVjvZWZVpnMnXi9sWGdgUpxsCuAIROXjZ40 |
9 |
IRZ2C9EouwJBAOPjPvV8Sgw4vaseOqlJvSq/C/pIFx6RVznDGlc8bRg7SgTPpjHG |
10 |
4G+M3mVgpCX1a/EU1mB+fhiJ2LAZ/pTtY6sCQGaW9NwIWu3DRIVGCSMm0mYh/3X9 |
11 |
DAcwLSJoctiODQ1Fq9rreDE5QfpJnaJdJfsIJNtX1F+L3YceeBXtW0Ynz2MCQBI8 |
12 |
9KP274Is5FkWkUFNKnuKUK4WKOuEXEO+LpR+vIhs7k6WQ8nGDd4/mujoJBr5mkrw |
13 |
DPwqA3N5TMNDQVGv8gMCQQCaKGJgWYgvo3/milFfImbp+m7/Y3vCptarldXrYQWO |
14 |
AQjxwc71ZGBFDITYvdgJM1MTqc8xQek1FXn1vfpy2c6O |
15 |
----- END RSA PRIVATE KEY-----'; |
17 |
$publicKey = '-----BEGIN PUBLIC KEY----- |
18 |
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZsfv1qscqYdy4vY+P4e3cAtmv |
19 |
ppXQcRvrF1cB4drkv0haU24Y7m5qYtT52Kr539RdbKKdLAM6s20lWy7+5C0Dgacd |
20 |
wYWd/7PeCELyEipZJL07Vro7Ate8Bfjya+wltGK9+XNUIHiumUKULW4KDx21+1NL |
21 |
AUeJ6PeW+DAkmJWF6QIDAQAB |
22 |
----- END PUBLIC KEY-----'; |
24 |
function rsaEncrypt( $data ) |
27 |
openssl_public_encrypt( $data , $crypted , $publicKey ); |
31 |
function rsaDecrypt( $data ) |
34 |
openssl_private_decrypt( $data , $decrypted , $privateKey ); |
40 |
$crypted = rsaEncrypt( "polaris@studygolang.com" ); |
41 |
$decrypted = rsaDecrypt( $crypted ); |
42 |
echo "encrypt and decrypt:" . $decrypted ; |
这里也是用PHP加解密polaris@studygolang.com
2、Go和PHP一起工作
这里要注意的一点是,由于加密后是字节流,直接输出查看会乱码,因此,为了便于语言直接加解密,这里将加密之后的数据进行base64编码。
完整代码放在了github上
https://github.com/polaris1119/myblog_article_code/tree/master/rsa
3、使用
示例中,php和Go版本都支持-d参数传入加密好的字符串,将其解密;不传时,会输出加密好并base64编码的串,可用于其他语言解密。
- RSA加密解密及RSA加签验签
RSA安全性应用场景说明 在刚接触RSA的时候,会混淆RSA加密解密和RSA加签验签的概念.简单来说加密解密是公钥加密私钥解密,持有公钥(多人持有)可以对数据加密,但是只有持有私钥(一人持有)才可以解 ...
- RSA加密解密及RSA签名和验证及证书
RSA加密解密及RSA签名和验证及证书 公钥是给别人的 发送密文使用公钥加密 验证签名使用公钥验证 私钥是自己保留的 接受密文使用私钥解密 发送签名使用私钥签名 上述过程逆转是不行的,比如使用私钥加密 ...
- RSA加密解密及RSA签名和验证
原文:RSA加密解密及RSA签名和验证 1.RSA加密解密: (1)获取密钥,这里是产生密钥,实际应用中可以从各种存储介质上读取密钥 (2)加密 (3)解密2.RSA签名和验证 (1)获取密钥,这里是 ...
- 加密解密 AES RSA MD5 SHA
加密解密: 对称加密:加密和解密相同秘钥.常见算法:AES, XTEA, 3DES. 非对称加密: 公钥加密 私钥加密. 加密和解密秘钥不同.常见算法:RSA OpenSSL> genrsa - ...
- 银联手机支付(.Net Csharp),3DES加密解密,RSA加密解密,RSA私钥加密公钥解密,.Net RSA 3DES C#
前段时间做的银联支付,折腾了好久,拼凑的一些代码,有需要的朋友可以参考,本人.Net新手,不保证准确性! 这个银联手机支付没有SDK提供,技术支持也没有.Net的,真心不好搞! RSA加解密,这里有个 ...
- .net core AES加密解密及RSA 签名验签
引用 using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Security; using System; using Sy ...
- 加密解密(6)RSA算法过程图解
转自: http://blog.csdn.net/21aspnet/article/details/7249401 RSA算法 RSA公钥加密算法是1977年由Ron Rivest.Adi Shami ...
- C#加密解密(DES,AES,Base64,md5,SHA256,RSA,RC4)
一:异或^简单加解密(数字类型) 1:原理: 异或用于比较两个二进制数的相应位,在执行按位"异或"运算时,如果两个二进制数的相应位都为1或者都为0,则返回0;如果两个二进制数的相应 ...
- RSA加密解密和读取公钥、私钥
/// <summary> /// RSA加密解密及RSA签名和验证 /// </summary> public class RSADE { ...
随机推荐
- sql 取首次投资的人
--- 11月 ---首次投资笔数和投资金额 ) AS stNum,sum(amount) AS stAmount FROM ( ),createtime,) AS riqi,a.amount,a.u ...
- 再谈:jquery编写插件的方法
版权声明:作者原创,转载请注明出处! 编写插件的两种方式: 1.类级别开发插件(1%) 2.对象级别开发(99%) 类级别的静态开发就是给jquery添加静态方法,三种方式 1.添加新的全局函数 2. ...
- Paip.最佳实践-- Buildin variale 内建变量 ,魔术变量,预定义变量,系统常量,系统变量 1
Paip.最佳实践-- Buildin variale 内建变量 ,魔术变量,预定义变量,系统常量,系统变量 1.1.1 C++内建变量(__LINE__).... 1.1.2 ...
- iOS开发--JSON
1.什么是JSON? JSON(JavaScript Object Notation)在网络传输中几乎无处不在,JSON是一种轻量级的数据交换格式,是基于JavaScript(Standard ECM ...
- WindowsPhone8拍照功能实现简介
WindowsPhone作为一款智能手机操作系统,支持APP中拍照是必不可少的,目前在WP8上的拍照主要有以下三种途径: 1.使用CameraCaptureTask: 2.使用PhotoCamera类 ...
- android: 后台执行的定时任务
Android 中的定时任务一般有两种实现方式,一种是使用 Java API 里提供的 Timer 类, 一种是使用 Android 的 Alarm 机制.这两种方式在多数情况下都能实现类似的效果,但 ...
- 一致性hash和solr千万级数据分布式搜索引擎中的应用
互联网创业中大部分人都是草根创业,这个时候没有强劲的服务器,也没有钱去买很昂贵的海量数据库.在这样严峻的条件下,一批又一批的创业者从创业中 获得成功,这个和当前的开源技术.海量数据架构有着必不可分的关 ...
- 为什么Android的图片质量会比iPhone的差?
经常看到有人问:“安卓版微信发出去的图片怎么那么渣!比iPhone的差远了!”.不只是微信,很多应用安卓版的图片质量就是要比iPhone版逊色很多,这到底是怎么回事? 我们团队最初也纠结 ...
- Jenkins 插件 CIFS
Jenkis编译后我们往往需要把文件发布的其他的服务器上,典型的插件如下: Publish Over CIFS Plugin Publish Over FTP Plugin Publish ...
- Android带多选功能的PhotoPicker
最近利用闲碎的一些时间开发了一个Android库PhotoPicker,前面一篇文章也介绍了,Android高仿微信图片选择功能的PhotoPicker,之前没有加入选择多张图片的功能,现在加上之后一 ...