Linux下实现加签、验签
1.使用OpenSSL 生成公钥和密钥;
#用 OpenSSL, Linux 上自带,常用命令如下:
#生成 RSA 私钥(传统格式的)
#用 OpenSSL, Linux 上自带,常用命令如下:
#生成 RSA 私钥(传统格式的)
openssl genrsa -out rsa_private_key.pem 1024
#将传统格式的私钥转换成 PKCS#8 格式的(JAVA需要使用的私钥需要经过PKCS#8编码,PHP程序不需要,可以直接略过)
openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt
#生成 RSA 公钥
openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
2.使用私钥对文件进行加签、并验证
#有明文文件file.txt和RSA密钥rsa_private_key.pem
#使用md5指令指定sha1算法,对file.txt进行签名,生成签名文件sign1.txt
openssl md5 -sha512 -sign rsa_private_key.pem -out data_xinbao.tar.gz.sign data_xinbao.tar.gz
#使用md5指令指定sha1算法,对file.txt进行签名,生成签名文件sign1.txt
openssl dgst -sha512 -sign rsa_private_key.pem -out data_xinbao.tar.gz.sign data_xinbao.tar.gz
#两个签名文件一样,说明两个指令完成相同的功能
diff data_xinbao.tar.gz.sign data_xinbao1.tar.gz.sign
#使用RSA公钥验证签名(verify参数),验证成功
openssl md5 -verify rsa_public_key.pem -sha512 -signature data_xinbao1.tar.gz.sign data_xinbao.tar.gz
openssl dgst -verify rsa_public_key.pem -sha512 -signature data_xinbao.tar.gz.sign data_xinbao.tar.gz
3.查看OpenSSL和帮助
#通过下面命令可以查看openssl的参数说明
$ openssl dgst -
options are
-c to output the digest with separating colons
-r to output the digest in coreutils format
-d to output debug info
-hex output as hex dump
-binary output in binary form
-sign file sign digest using private key in file
-verify file verify a signature using public key in file
-prverify file verify a signature using private key in file
-keyform arg key file format (PEM or ENGINE)
-out filename output to filename rather than stdout
-signature file signature to verify
-sigopt nm:v signature parameter
-hmac key create hashed MAC with key
-mac algorithm create MAC (not neccessarily HMAC)
-macopt nm:v MAC algorithm parameters or key
-engine e use engine e, possibly a hardware device.
-md4 to use the md4 message digest algorithm
-md5 to use the md5 message digest algorithm
-ripemd160 to use the ripemd160 message digest algorithm
-sha to use the sha message digest algorithm
-sha1 to use the sha1 message digest algorithm
-sha224 to use the sha224 message digest algorithm
-sha256 to use the sha256 message digest algorithm
-sha384 to use the sha384 message digest algorithm
-sha512 to use the sha512 message digest algorithm
-whirlpool to use the whirlpool message digest algorithm
4.拿加签的原文件和加签后的文件使用Java代码进行对比;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.*;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Date;
/**
* 对文件加签、验签工具类
* 生成私钥:openssl genrsa -out rsa_private_key.pem 1024
* 私钥还不能直接被使用,需要进行PKCS#8编码:openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt
* 根据私钥生成公钥:openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
* 使用私钥sha512签名:openssl dgst -sha512 -sign rsa_private_key.pem -out xx.tar.gz.sign xx.tar.gz
* 使用公钥sha512验签:openssl dgst -verify rsa_public_key.pem -sha512 -signature xx.tar.gz.sign xx.tar.gz
* @author XIHONGLIE
* @date 2018-03-27
*/
public class RsaEncrypt {
/**
* rsa签名
* @param data 待签名的字符串
* @param priKey rsa私钥字符串
* @return 签名结果
* @throws Exception 签名失败则抛出异常
*/
public byte[] rsaSign(byte[] data, RSAPrivateKey priKey)
throws SignatureException {
try {
Signature signature = Signature.getInstance("SHA512withRSA");
signature.initSign(priKey);
signature.update(data);
byte[] signed = signature.sign();
return signed;
} catch (Exception e) {
throw new SignatureException("RSAcontent = " + data
+ "; charset = ", e);
}
}
/**
* rsa验签
* @param data 被签名的内容
* @param sign 签名后的结果
* @param pubKey rsa公钥
* @return 验签结果
* @throws SignatureException 验签失败,则抛异常
*/
public boolean verify(byte[] data, byte[] sign, RSAPublicKey pubKey)
throws SignatureException {
try {
Signature signature = Signature.getInstance("SHA512withRSA");
signature.initVerify(pubKey);
signature.update(data);
return signature.verify(sign);
} catch (Exception e) {
e.printStackTrace();
throw new SignatureException("RSA验证签名[content = " + data
+ "; charset = " + "; signature = " + sign + "]发生异常!", e);
}
}
/**
* 私钥
*/
private RSAPrivateKey privateKey;
/**
* 公钥
*/
private RSAPublicKey publicKey;
/**
* 字节数据转字符串专用集合
*/
private static final char[] HEX_CHAR = {
'0', '1', '2', '3', '4', '5', '6',
'7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
/**
* 获取私钥
* @return 当前的私钥对象
*/
public RSAPrivateKey getPrivateKey() {
return privateKey;
}
/**
* 获取公钥
* @return 当前的公钥对象
*/
public RSAPublicKey getPublicKey() {
return publicKey;
}
/**
* 随机生成密钥对
*/
public void genKeyPair() {
KeyPairGenerator keyPairGen = null;
try {
keyPairGen = KeyPairGenerator.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
keyPairGen.initialize(1024, new SecureRandom());
KeyPair keyPair = keyPairGen.generateKeyPair();
this.privateKey = (RSAPrivateKey) keyPair.getPrivate();
this.publicKey = (RSAPublicKey) keyPair.getPublic();
}
/**
* 从.pem文件中取得私钥
* @param filePath 文件路径
* @return 私钥
*/
public String getPrivateKeyFromFile(String filePath){
String strPrivateKey = "";
try {
BufferedReader privateKey = new BufferedReader(new FileReader(filePath));
String line = "";
while((line = privateKey.readLine()) != null){
strPrivateKey += line;
}
privateKey.close();
strPrivateKey = strPrivateKey.replace("-----BEGIN PRIVATE KEY-----","").replace("-----END PRIVATE KEY-----","");
}catch (Exception e){
e.printStackTrace();
}
return strPrivateKey;
}
/**
* 从.pem文件中取得公钥
* @param filePath 文件路径
* @return 公钥
*/
public String getPublicKeyFromFile(String filePath){
String strPublicKey = "";
try {
BufferedReader publicKey = new BufferedReader(new FileReader(filePath));
String line = "";
while((line = publicKey.readLine()) != null){
strPublicKey += line;
}
publicKey.