java rsa私钥加密是一种加密算法。私钥加密算法是用私钥来进行加密与解密信息。私钥加密也被称作对称加密,原因是加密与解密使用的秘钥是同一个。
RSA加密需要注意的事项如下:
1. 首先产生公钥与私钥
2. 设计加密与解密的算法
3. 私钥加密的数据信息只能由公钥可以解密
4. 公钥加密的数据信息只能由私钥可以解密
实战演练,具体步骤如下: public class RsaCryptTools { private static final String CHARSET = "utf-8" private static final Base64.Decoder decoder64 = Base64.getDecoder() private static final Base64.Encoder encoder64 = Base64.getEncoder() /** * 生成公私钥 * @param keySize * @return * @throws NoSuchAlgorithmException */ public static SecretKey generateSecretKey(int keySize) throws NoSuchAlgorithmException { //生成密钥对 KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA") keyGen.initialize(keySize, new SecureRandom()) KeyPair pair = keyGen.generateKeyPair() PrivateKey privateKey = pair.getPrivate() PublicKey publicKey = pair.getPublic() //这里可以将密钥对保存到本地 return new SecretKey(encoder64.encodeToString(publicKey.getEncoded()), encoder64.encodeToString(privateKey.getEncoded())) } /** * 私钥加密 * @param data * @param privateInfoStr * @return * @throws IOException * @throws InvalidCipherTextException */ public static String encryptData(String data, String privateInfoStr) throws IOException, InvalidKeySpecException, NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding") cipher.init(Cipher.ENCRYPT_MODE, getPrivateKey(privateInfoStr)) return encoder64.encodeToString(cipher.doFinal(data.getBytes(CHARSET))) } /** * 公钥解密 * @param data * @param publicInfoStr * @return */ public static String decryptData(String data, String publicInfoStr) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException { byte[] encryptDataBytes=decoder64.decode(data.getBytes(CHARSET)) //解密 Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding") cipher.init(Cipher.DECRYPT_MODE, getPublicKey(publicInfoStr)) return new String(cipher.doFinal(encryptDataBytes), CHARSET) } private static PublicKey getPublicKey(String base64PublicKey) throws NoSuchAlgorithmException, InvalidKeySpecException { X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(base64PublicKey.getBytes())) KeyFactory keyFactory = KeyFactory.getInstance("RSA") return keyFactory.generatePublic(keySpec) } private static PrivateKey getPrivateKey(String base64PrivateKey) throws NoSuchAlgorithmException, InvalidKeySpecException { PrivateKey privateKey = null PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(base64PrivateKey.getBytes())) KeyFactory keyFactory = null keyFactory = KeyFactory.getInstance("RSA") privateKey = keyFactory.generatePrivate(keySpec) return privateKey } /** * 密钥实体 * @author hank * @since 2020/2/28 0028 下午 16:27 */ public static class SecretKey { /** * 公钥 */ private String publicKey /** * 私钥 */ private String privateKey public SecretKey(String publicKey, String privateKey) { this.publicKey = publicKey this.privateKey = privateKey } public String getPublicKey() { return publicKey } public void setPublicKey(String publicKey) { this.publicKey = publicKey } public String getPrivateKey() { return privateKey } public void setPrivateKey(String privateKey) { this.privateKey = privateKey } @Override public String toString() { return "SecretKey{" + "publicKey='" + publicKey + '\'' + ", privateKey='" + privateKey + '\'' + '}' } } private static void writeToFile(String path, byte[] key) throws IOException { File f = new File(path) f.getParentFile().mkdirs() try(FileOutputStream fos = new FileOutputStream(f)) { fos.write(key) fos.flush() } } public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, IOException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException, InvalidKeySpecException { SecretKey secretKey = generateSecretKey(2048) System.out.println(secretKey) String enStr = encryptData("你好测试测试", secretKey.getPrivateKey()) System.out.println(enStr) String deStr = decryptData(enStr, secretKey.getPublicKey()) System.out.println(deStr) enStr = encryptData("你好测试测试hello", secretKey.getPrivateKey()) System.out.println(enStr) deStr = decryptData(enStr, secretKey.getPublicKey()) System.out.println(deStr) } }
DES加密DES是一种对称加密(Data Encryption Standard)算法,以前我写过一篇文章:.NET中加密解密相关知识,有过简单描述。
DES算法一般有两个关键点,第一个是加密算法,第二个是数据补位。
加密算法常见的有ECB模式和CBC模式:
ECB模式:电子密本方式,这是JAVA封装的DES算法的默认模式,就是将数据按照8个字节一段进行DES加密或解密得到一段8个字节的密文或者明文,最后一段不足8个字节,则补足8个字节(注意:这里就涉及到数据补位了)进行计算,之后按照顺序将计算所得的数据连在一起即可,各段数据之间互不影响。
CBC模式:密文分组链接方式,这是.NET封装的DES算法的默认模式,它比较麻烦,加密步骤如下:
1、首先将数据按照8个字节一组进行分组得到D1D2......Dn(若数据不是8的整数倍,就涉及到数据补位了)
2、第一组数据D1与向量I异或后的结果进行DES加密得到第一组密文C1(注意:这里有向量I的说法,ECB模式下没有使用向量I)
3、第二组数据D2与第一组的加密结果C1异或以后的结果进行DES加密,得到第二组密文C2
4、之后的数据以此类推,得到Cn
5、按顺序连为C1C2C3......Cn即为加密结果。
数据补位一般有NoPadding和PKCS7Padding(JAVA中是PKCS5Padding)填充方式,PKCS7Padding和PKCS5Padding实际只是协议不一样,根据相关资料说明:PKCS5Padding明确定义了加密块是8字节,PKCS7Padding加密快可以是1-255之间。但是封装的DES算法默认都是8字节,所以可以认为他们一样。数据补位实际是在数据不满8字节的倍数,才补充到8字节的倍数的填充过程。
NoPadding填充方式:算法本身不填充,比如.NET的padding提供了有None,Zeros方式,分别为不填充和填充0的方式。
PKCS7Padding(PKCS5Padding)填充方式:为.NET和JAVA的默认填充方式,对加密数据字节长度对8取余为r,如r大于0,则补8-r个字节,字节为8-r的值;如果r等于0,则补8个字节8。比如:
加密字符串为为AAA,则补位为AAA55555加密字符串为BBBBBB,则补位为BBBBBB22;加密字符串为CCCCCCCC,则补位为CCCCCCCC88888888。
.NET中的DES加密
对于.NET,框架在System.Security.Cryptography命名空间下提供了DESCryptoServiceProvider作为System.Security.Cryptography.DES加密解密的包装接口,它提供了如下的4个方法:
public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] rgbIV)
public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] rgbIV)
public override void GenerateIV()
public override void GenerateKey()