1.生成签名与验签
相关函数
openssl_get_privatekey()
获取私钥文件的内容
openssl_sign()
私钥生成签名
opensll_get_publickey()
获取公钥文件的内容
opensll_veriry()
公钥验证签名
生成公钥和私钥
常用的rsa密钥有两种格式:
- pkcs1格式
# 公钥
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
# 私钥
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----
- pkcs8格式
# 公钥
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
# 私钥
-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----
php中使用的是pkcs1格式的,java中使用的是pkcs8格式的,这里都做一下介绍。
下面开始生成公钥和私钥文件:
- 生成原始 RSA私钥文件 rsa_private_key.pem
openssl genrsa -out rsa_private_key.pem 1024
- 将原始 RSA私钥转换为 pkcs8格式,JAVA需要使用的私钥需要经过 PKCS8 编码
openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt -out rsa_private_key_java.pem
- 生成 RSA公钥 rsa_public_key.pem
openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
- 生成 RSA公钥 rsa_public_key_java.pem,PKCS8 对应的公钥
openssl rsa -in rsa_private_key_java.pem -pubout -out rsa_public_key_java.pem
- 从公钥 rsa_public_key.pem 获取十六进制的公钥(第一段16进制字符串)
openssl asn1parse -out -i -inform PEM<rsa_private_key.pem
- 从公钥 rsa_public_key.pem 获取十六进制的公钥(第一段16进制字符串) PKCS8 对应的十六进制的公钥
openssl asn1parse -out temp_java.ans -i -inform PEM<rsa_private_key_java.pem
生成签名
<?php
// 私钥路径
$rsaPrivateKeyPath = '/home/rsa_private_key.pem';
// 获取私钥的内容
$fileContent = file_get_contents($rsaPrivateKeyPath);
// 获取私钥资源对象
$privateKey = opensll_get_privatekey($fileContent);
// 待签名字符串
$data = 'id=1&name=xiaoming';
// 进行签名
openssl_sign($data, $sign, $privateKey);
// 为了防止乱码对签名结果进行base64转码
$sign = base64_encode($sign);
校验签名
<?php
// 公钥路径
$rsaPublicKeyPath = '/home/rsa_public_key.pem';
// 获取公钥内容
$fileContent = file_get_content($rsaPublicKeyPath);
// 获取公钥内容
$publicKey = openssl_get_publickey($fileContent);
// 待校验的签名字符串
$data = 'id=1&name=xiaoming';
// 进行校验
// 已知签名字符串
$sing = '1341rqeqrrweq';
// 因为我这上面是进行了base64转码的,所以这里要先解码
$result = openssl_verify($data, base64_decode($sign), $publicKey);
双向加密
相关函数
openssl_public_encrypt()
公钥加密
opensll_public_decrypt()
公钥解密
openssl_private_encrypt()
私钥加密
openssl_private_decrypt()
私钥解密
公钥加密与私钥解密
加密
<?php
// 公钥路径
$rsaPublicKeyPath = '/home/rsa_public_key.pem';
$fileContent = file_get_content($rsaPublicKeyPath);
// 获取公钥内容
$publicKey = openssl_get_publickey($fileContent);
// 待校验的签名字符串
$data = 'id=1&name=xiaoming';
// 进行加密
openssl_public_encrypt($data, $encryptData, $publicKey);
// 防止乱码进行base64转码,解密时也要先base64_decode
$result = base64_encode($encryptData);
解密
<?php
// 公钥路径
$rsaPublicKeyPath = '/home/rsa_public_key.pem';
$fileContent = file_get_content($rsaPublicKeyPath);
// 获取公钥内容
$publicKey = openssl_get_publickey($fileContent);
// 已加密的字符串
$data = 'afafadfasd';
// 进行加密
openssl_public_decrypt(base64_decode($data), $decryptData, $publicKey);
// 解密结果
$result = $decryptData;
js rsa加密与解密
注意js中传的公钥或私钥都是不带-----
的开头的字符串,而且没有换行。
<script src="/scripts/"></script>
<script>
function encrypt(str) {
var encrypt = new JSEncrypt();
encrypt.setPublicKey('ttxseokm4vQTWukPqEthBWSdqlC/+6FM74z2Oi506y+LSRNcMijeUEm2hYRM9x2+zh0cvVA2iCM71KaxcFlzUl9tUxBAPr7S0hOwCQIDAQAB');
var data = encrypt.encrypt(str);
return data;
}
function decrypt(encrypted) {
var decrypt = new JSEncrypt();
decrypt.setPrivateKey('1111adfasdasdaf');
var uncrypted = decrypt.decrypt(encrypted);
return uncrypted;
}
</script>
说明:公钥加密的数据需要使用私钥进行解密,同理,私钥加密的数据需要使用公钥才能进行解密。
私钥进行加密与解密的用法与公钥一样,不再举例。
双向加密
相关函数
openssl_get_cipher_methods()
可用的加密算法列表
openssl_cipher_iv_length()
获取指定算法的iv初始化向量的长度
openssl_random_pseudo_bytes($len)
随机获取一个指定长度的初始化向量
openssl_encrypt()
加密
openssl_decrypt()
解密
加密
加密所使用的函数为openssl_encrypt($data, $method, $key, $options, $iv)
,参数说明如下:
-
$data
待签名字符串 -
$method
所采用的加密算法,如des-ecb
-
$key
加密采用密钥 -
$options
可选, 填充方式,默认使用0即可,不同的语言之间如果出现解密不了的情况,一种是算法错误,另一种情况就是使用的填充方式不同 -
$iv
可选,初始化向量
特别说明:不同的加密算法对应着不同长度的初始化向量长度,指定的加密算法所需要的初始化向量长度可以使用函数openssl_cipher_iv_length($method)
获取。有一些算法的初始化向量的长度为0,那么使用这些算法的时候,不需要传$iv
这个参数,如des-ecb
的初始化向量的长度为0,使用这种加密算法时不需要传$iv
参数
下面以des-ecb
算法为例:
js下载链接:
- 加密
<?php
// 密钥
$key = 'adfafvadfa1e1';
// 待加密数据
$data = '1832587802';
// 加密方式
$method = 'des-ecb';
$result = openssl_encrypt($data, $method, $key);
// 注意返回的结果是base64的结果,如果与其它语言共同调试时可能返回的是乱码需要再base64一下
- 解密
<?Php
// 密钥
$key = 'adfafvadfa1e1';
// 待解密数据
$data = 'ma7oRNLDBkoHaPw5DcLRhg==';
// 加密方式
$method = 'des-ecb';
$result = openssl_decrypt($data, $method, $key);
js加密
以下是js示例代码与phpdes-ecb对应:
js下载链接/noteshare?id=e6532e12c49730042740414b25bfeb5e&sub=861CE888ECD44DAFAD76EF7D1E61C815
<script src="./cryptojs/rollups/"></script>
<script src="./cryptojs/components/"></script>
<script>
// DES加密
function encryptByDES(message, key) {
var keyHex = CryptoJS.enc.Utf8.parse(key);
var encrypted = CryptoJS.DES.encrypt(message, keyHex, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
return encrypted.toString();
}
//DES 解密
function decryptByDES(ciphertext, key) {
var keyHex = CryptoJS.enc.Utf8.parse(key);
// direct decrypt ciphertext
var decrypted = CryptoJS.DES.decrypt({
ciphertext: CryptoJS.enc.Base64.parse(ciphertext)
}, keyHex, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
//这一步 是来填写 加密时候填充方式 padding: .Pkcs7
});
return decrypted.toString(CryptoJS.enc.Utf8);
}
</script>