我们一般的加密主要分2种。对称加密。非对称加密。顾名思义。对称加密就是秘钥是一样的。通过同一个秘钥加密解密。这一类的加密算法有DES,3DES,AES等。而非对称加密即使用公钥和秘钥2个。公钥进行加密,而私钥进行解密。这一类的加密算法主要RSA
数字签名并不是加密。他只是将传递的参数进行签名。服务器端可以验签。主要作用有2个:1.保证数据不会被篡改。2.保证请求的确是秘钥持有者发送的。 虽然他不是加密但是这里我们使用到了RSA加密。sha1withrsa顾名思义。是将加密对象进行sha1后进行rsa加密。当然。并不是简单的sha1后就直接rsa。中间有一些处理。具体的细节我不是很了解。也不需要了解除非你对算法极度感兴趣。可以去找找资料弄明白。不管怎样处理。最后我们得到了用rsa秘钥加密后的数据。一般情况下我们会base64成一个字符串,方便传输。这样的字符串就是数字签名了。服务器端只需要用对应的公钥进行验签就可以判断出是不是秘钥持有者发送的消息了。
总结起来就是非对称加密的公钥可以对被私钥加密的数据进行验签,而被公钥加密的数据私钥可以进行解密。
自己生成公钥秘钥一般情况下就需要使用openssl工具了。使用工具执行命令
genrsa -out rsa_private_key.pem 2048
2048指的是位数。一般情况下1024也够用了。如果要求高点还是2048位更加合适点。生成的pem文件里面以-----BEGIN RSA PRIVATE KEY-----开头-----END RSA PRIVATE KEY-----结尾的字符串。中间的部分才是秘钥的base64字符串.这个是pkcs1格式的。也就是原本的rsa密钥。
rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
上面的命令会根据刚刚的私钥生成pkcs8格式的公钥。
如果需要pkcs8个格式的私钥(java就是用pkcs8格式的)需要
pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt
会打印出来以-----BEGIN PRIVATE KEY-----开头。以-----END PRIVATE KEY-----结尾的私钥。
这里我们需要了解一下pkcs1格式和pkcs8格式的区别和关联:
pkcs1的格式才是原本的rsa的密钥。而pkcs8的格式是在pkcs1的数据上增加一些信息。具体这些信息是什么我并没有去深入了解。我们只需要知道pkcs1和pkcs8之间是可以转换的。
从文件获取公钥、私钥
public static PublicKey loadPublicKeyFromFile(String publicKeyFileName) {
InputStream fis;
PublicKey pubKey = null;
try {
fis = new FileInputStream(publicKeyFileName);
CertificateFactory cf = CertificateFactory.getInstance("x509");
Certificate cerCert = cf.generateCertificate(fis);
pubKey = cerCert.getPublicKey();
} catch (FileNotFoundException | CertificateException e) {
e.printStackTrace();
}
return pubKey;
}
public static PrivateKey loadPriviteKeyFromFile(String privateKeyFileName, String aliasName, String password) {
InputStream fis;
PrivateKey priKey = null;
try {
fis = new FileInputStream(privateKeyFileName);
KeyStore keyStore = KeyStore.getInstance("PKCS12");
char[] pscs = password.toCharArray();
keyStore.load(fis, pscs);
priKey = (PrivateKey) (keyStore.getKey(aliasName, pscs));
} catch (Exception e) {
e.printStackTrace();
}
return priKey;
}
直接获取公钥、私钥
/**
*@stored 公钥明文
*/
public static Key loadPublicKey(String stored) throws GeneralSecurityException, IOException {
byte[] data = Base64.getDecoder().decode((stored.getBytes()));
X509EncodedKeySpec spec = new X509EncodedKeySpec(data);
KeyFactory fact = KeyFactory.getInstance("RSA");
return fact.generatePublic(spec);
}
/**
* @key64 私钥明文
*/
public static Key loadPrivateKey(String key64) throws GeneralSecurityException, IOException {
byte[] clear = Base64.getDecoder().decode(key64.getBytes());
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(clear);
KeyFactory fact = KeyFactory.getInstance("RSA");
PrivateKey priv = fact.generatePrivate(keySpec);
Arrays.fill(clear, (byte) 0);
return priv;
}
私钥签名,公钥验签
/**
* 私钥签名
* @str 待签名的数据
* @return 签名后经过base64处理的字符串
* @throws Exception
*/
public static String sign(String str) {
String base64Sign = "";
InputStream fis = null;
try {
fis = new FileInputStream(privateKeyFileName);
KeyStore keyStore = KeyStore.getInstance("PKCS8");
char[] pscs = pfxPassword.toCharArray();
keyStore.load(fis, pscs);
PrivateKey priKey = (PrivateKey) (keyStore.getKey(aliasName, pscs));
// 签名
Signature sign = Signature.getInstance("SHA1withRSA");
sign.initSign(priKey);
byte[] bysData = str.getBytes("UTF-8");
sign.update(bysData);
byte[] signByte = sign.sign();
BASE64Encoder encoder = new BASE64Encoder();
base64Sign = encoder.encode(signByte);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return base64Sign;
}
/**
* 公钥验签
* @param signStr 加密后的数据
* @param verStr 原始字符
* @return
*/
public static boolean verify(String signStr, String verStr)
throws Exception {
boolean verfy = false;
InputStream fis = null;
try {
fis = new FileInputStream(publicKeyFileName);
CertificateFactory cf = CertificateFactory.getInstance("x509");
Certificate cerCert = cf.generateCertificate(fis);
PublicKey pubKey = cerCert.getPublicKey();
BASE64Decoder decoder = new BASE64Decoder();
byte[] signed = decoder.decodeBuffer(signStr);
Signature sign = Signature.getInstance("SHA1withRSA");
sign.initVerify(pubKey);
sign.update(verStr.getBytes("UTF-8"));
verfy = sign.verify(signed);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return verfy;
}
公钥加密、私钥解密
/**
* 通过公钥文件进行加密数据
* @return 加密后经过base64处理的字符串
*/
public static String encrypt(String source) throws Exception {
InputStream fis = null;
try {
fis = new FileInputStream(publicKeyFileName);
CertificateFactory cf = CertificateFactory.getInstance("x509");
Certificate cerCert = cf.generateCertificate(fis);
PublicKey pubKey = cerCert.getPublicKey();
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] sbt = source.getBytes();
byte[] epByte = cipher.doFinal(sbt);
BASE64Encoder encoder = new BASE64Encoder();
String epStr = encoder.encode(epByte);
return epStr;
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 通过私钥文件进行解密数据
* @return 解密后的明文字符串
*/
public static String decode(String source) throws Exception {
BASE64Decoder b64d = new BASE64Decoder();
byte[] keyByte = b64d.decodeBuffer(source);
InputStream fis = null;
try {
fis = new FileInputStream(privateKeyFileName);
KeyStore keyStore = KeyStore.getInstance("PKCS8");
char[] pscs = pfxPassword.toCharArray();
keyStore.load(fis, pscs);
PrivateKey priKey = (PrivateKey) (keyStore.getKey(aliasName, pscs));
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, priKey);
byte[] epByte = cipher.doFinal(keyByte);
return new String(epByte, "UTF-8");
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}