0


Java加解密(四)非对称加密

目录

非对称加密

1 定义

非对称加密算法需要两个密钥:公开密钥(publickey:简称公钥)和私有密钥(privatekey:简称私钥)。公钥与私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。

2 特点

  1. 也称公开密钥加密,算法需要两个密钥,其中一个可以公开,并且通过公开的密钥无法推导出对应的私钥
  2. 算法复杂度相对对称加密算法高,所以计算相对较慢
  3. 密钥的保密性较好,因为公钥可以公开,免去了交换密钥的需求

3 使用场景

由于安全性较好,并且密钥可以公开,无交换过程泄密的风险,因此非对此密钥算法被广泛使用,比如SSH、HTTPS、电子证书、数字签名、加密通讯等领域。
公钥既可以进行加密,也可以解密,私钥也是一样,用于支持不同场景:

  1. 使用私钥加密,公钥解密 这种就是数字签名的原理,用于让所有公钥所有者验证私钥所有者的身份并且用来防止私钥所有者发布的内容被篡改(只有唯一的一方持有私钥,加密者一定是唯一确定的,除非私钥泄露了),但是不用来保证内容不被他人获得(公钥是公开的,所有持有公钥的一方都能解密这段密文)
  2. 用公钥加密,私钥解密 这种就是数据加密,用于公钥所有者向私钥所有者发布信息,这个信息可能被他人篡改(因为持有公钥的一方都能生成一段新的密文,可以替换掉原始密文),但是无法被他人获得(只有私钥所有者一人能够解密这段密文)
  3. 甲方用公钥-乙加密,私钥-甲加密,乙方用公钥-甲解密,私钥-乙解密 如果甲想给乙发一个安全的保密的数据,那么应该甲乙各自有一个私钥,甲先用乙的公钥加密这段数据,再用自己的私钥加密这段加密后的数据,最后再发给乙,这样确保了内容即不会被读取,也不会被篡改。

4 常用的非对称加密算法

1977年,三位数学家Rivest、Shamir 和 Adleman 设计了一种算法,可以实现非对称加密。这种算法用他们三个人的名字命名,叫做RSA算法,RSA算法从被发明至今一直是最广为使用的"非对称加密算法"。其他场景的算法还有Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)。

5 JDK支持的非对称加密算法

JDK8原生算法列表,可参第一篇博文: https://blog.csdn.net/yunyun1886358/article/details/128592503#311_JDK_Provider_63

6 Bouncy Castle 支持的非对称加密算法

Bouncy Castle算法列表,可参第一篇博文:
https://editor.csdn.net/md/?articleId=128592503#323_Bouncy_Castle_Provider_568

7 算法调用示例

下面的代码将JDK提供的几种RSA加密算法用枚枚举类进行了封装,调用encrypt()和decrypt()方法可以实现加密和解。encrypt()和decrypt()的几个重载方法分别支持了不同秘钥生成方式(秘钥字符串,随机种子生成秘钥,从文件读取密钥字符串,从数字证书读取公钥,从密钥库读取公钥,从密钥库读取私钥),设置算法参数的类型(AlgorithmParameterSpec)。

首先使用ktool生成密钥库,并导出公钥证书:

keytool -genkeypair -alias testing-keys -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore testing-keystore.p12 -validity 36500
keytool -list -v -keystore testing-keystore.p12
keytool -export -keystore testing-keystore.p12 -alias testing-keys -file testing-ca.cer -rfc
packagecom.qupeng.crypto.algorithm.oop;importcom.qupeng.crypto.util.CryptoUtils;importcom.qupeng.crypto.util.DigitalCertificationUtilsTest;importorg.junit.Assert;importorg.junit.BeforeClass;importorg.junit.Test;importjavax.crypto.BadPaddingException;importjavax.crypto.IllegalBlockSizeException;importjavax.crypto.NoSuchPaddingException;importjava.io.IOException;importjava.lang.reflect.InvocationTargetException;importjava.nio.file.Path;importjava.nio.file.Paths;importjava.security.InvalidAlgorithmParameterException;importjava.security.InvalidKeyException;importjava.security.NoSuchAlgorithmException;importjava.security.spec.InvalidKeySpecException;publicclassAsymmetricEncryptionAlgorithmTest{privatestaticPath keyStorePath;privatestaticPath certificatePath;@BeforeClasspublicstaticvoidsetUp()throwsException{
        keyStorePath =Paths.get(DigitalCertificationUtilsTest.class.getClassLoader().getResource("testing-keystore.p12").toURI());
        certificatePath =Paths.get(DigitalCertificationUtilsTest.class.getClassLoader().getResource("testing-ca.cer").toURI());}@TestpublicvoidencryptByRandomSeed()throwsException{// RSA 1024 bits secretString cipherText =AsymmetricEncryptionAlgorithm.RSA_ECB_PKCS1_PADDING_1024.encrypt("a","12345",NumberGenerationAlgorithm.SHA1_PRNG);Assert.assertEquals("a",AsymmetricEncryptionAlgorithm.RSA_ECB_PKCS1_PADDING_1024.decrypt(cipherText,"12345",NumberGenerationAlgorithm.SHA1_PRNG));// RSA 2048 bits secret
        cipherText =AsymmetricEncryptionAlgorithm.RSA_ECB_PKCS1_PADDING_2048.encrypt("a","12345",NumberGenerationAlgorithm.SHA1_PRNG);Assert.assertEquals("a",AsymmetricEncryptionAlgorithm.RSA_ECB_PKCS1_PADDING_2048.decrypt(cipherText,"12345",NumberGenerationAlgorithm.SHA1_PRNG));

        cipherText =AsymmetricEncryptionAlgorithm.RSA_ECB_OAEP_WITH_SHA_1_AND_MGF1_PADDING_1024.encrypt("a","12345",NumberGenerationAlgorithm.SHA1_PRNG);Assert.assertEquals("a",AsymmetricEncryptionAlgorithm.RSA_ECB_OAEP_WITH_SHA_1_AND_MGF1_PADDING_1024.decrypt(cipherText,"12345",NumberGenerationAlgorithm.SHA1_PRNG));

        cipherText =AsymmetricEncryptionAlgorithm.RSA_ECB_OAEP_WITH_SHA_256_AND_MGF1_PADDING_1024.encrypt("a","12345",NumberGenerationAlgorithm.SHA1_PRNG);Assert.assertEquals("a",AsymmetricEncryptionAlgorithm.RSA_ECB_OAEP_WITH_SHA_256_AND_MGF1_PADDING_1024.decrypt(cipherText,"12345",NumberGenerationAlgorithm.SHA1_PRNG));}@TestpublicvoidencryptByPublicKeyStr()throwsIllegalAccessException,NoSuchAlgorithmException,InstantiationException,NoSuchMethodException,InvalidKeyException,InvalidAlgorithmParameterException,NoSuchPaddingException,BadPaddingException,InvocationTargetException,IOException,InvalidKeySpecException,IllegalBlockSizeException{String cipherText =AsymmetricEncryptionAlgorithm.RSA_ECB_PKCS1_PADDING_1024.encrypt("a","MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiMkwWmWUG4DkC/1mIgL0BSBOLbQWgGL7XnaolDQbpKP5QZFCbWQqj2/Gvmhhk5QQAYoNAdfz1OXzZAJj2Zbp+/QtFWJhemV3ivSvBTXCVyhg39kGkUjniensW8oOwQiyNsXERDYeafXlahYRvFKgOj9BvUo1wDGuD4ESyAl89XLQOgez65J+kJhjh0vQCyPbMkNxp3qZ3vJ/OoA07OOsIOxoR15wdxTS5pvI8jZ+A8/LlFqUNaryv3kt/IBezn0DRnfwRx5Wl4RXZQpxeLleUX2HwhxBCA2ZZtTAYR/VX3fDI5MIC1kmZGfDLjnlOAPOVpJyxWN6yeWiDnkNNE6t1QIDAQAB");Assert.assertEquals("a",AsymmetricEncryptionAlgorithm.RSA_ECB_PKCS1_PADDING_1024.decrypt(cipherText,"MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCIyTBaZZQbgOQL/WYiAvQFIE4ttBaAYvtedqiUNBuko/lBkUJtZCqPb8a+aGGTlBABig0B1/PU5fNkAmPZlun79C0VYmF6ZXeK9K8FNcJXKGDf2QaRSOeJ6exbyg7BCLI2xcRENh5p9eVqFhG8UqA6P0G9SjXAMa4PgRLICXz1ctA6B7Prkn6QmGOHS9ALI9syQ3Gnepne8n86gDTs46wg7GhHXnB3FNLmm8jyNn4Dz8uUWpQ1qvK/eS38gF7OfQNGd/BHHlaXhFdlCnF4uV5RfYfCHEEIDZlm1MBhH9Vfd8MjkwgLWSZkZ8MuOeU4A85WknLFY3rJ5aIOeQ00Tq3VAgMBAAECggEAduHc24QTUEAac2092euVJ+tm5wPw1o6wh+47H+uV5ub4mIrmH+sBrn5oTk6sF7aEnsHcAjEtY2iju9Tz8UXfgLI8iKxjqhwL5MI6Zx3NFTEr2QFnWtfxHIUpfrFDV3P2Z/JEXUBn+JHVXPlnWrS5O0aFHT4lLzA+Zo04xJCygSON47XjHakAZdFV1EXVic523Rof2/G67NyG2FJOhytz6dh0S94KevLCbYm1FQbLNVIQkat6dGgzz7ahyiubWt9B/EQU3HgLgT5KDLUWzW57VFCZOAoHYxUKJ2UafaXYEAMMe4mh3ZPAOPpNYpPEcww09zFOFg9e7cpxi7ydSl42lQKBgQDCNqniS90UqNZMOJwHuO5vfRHNIwWpXNIpehAmfITECyJlChMJR0Y2ytN0KdTAUz6tK9v+gYhKE4cHpb/bj4qwqsWyQ7e9QgTq1U2ZH7lhIiRmux6E0ILf4O2JnYRl5HoHSt9efZ4yxFTQrcX2JENTDK17alYvwn9h1aoilfRZewKBgQC0TXH34fvCv4U81VjB0brheBd+edoJ2ZPW5W95CVOJBFXhMB2CMaqsxcxkMgidYOa9H01NbcIXA/s9Yyn2vzPGsqBvQthSillay32sVMBcq7JdOACL/atXBmYOnuUYs7hAbjIwRi9HOA+TJdgGgfLYsfr7vHMHnaJTqgS99Qos7wKBgQCJnkB9GTK8W/MWKZruoe1a1O4TRTjSzPIi79qX2u4dGKKzpBLfJUEsvEZf7vBRo+sqvIRz8IeJrhKlqZ6szycAjtHtwqxlEG35lVIaKe+rU40lunwisrm6OGE5fYN+zApoNnbXNv4tjQ9om2pGQ2XtaHNZm30c9J5czhFz1nxCFwKBgAR+HYXgsqZCoW5HnqONt0tg86zqGl2+dymWo/VvHw699enbihCxbiBJ+XLRsFdDj9xMiF+SiZCLP9piuyvzzbV4w/ihwMQlwF47zdDad8SXXqVl/NWAJ6HOfgKFQQ4hhEjOth9v0EPFCNZQzhYzbLqrjKZzJqac7euJw/57uZovAoGAdi57B+aHkK42Odb0l9q+u7Nu8C8v5A7j8LvycKY48QJKxP7GiztTAX/qEcfiVl3HvdOP1kECePxGX1ix3aAmmzJWnrrI5UVdzkXevrJSqEJkbCi0YwVPs26gHGfCVfNkX6jdCv4PrsPwUzNr0ld+Oi4T0Dmv2bi4/wuyLGumfuM="));}@TestpublicvoidencryptByPublicKeyFromFile()throwsIllegalAccessException,NoSuchAlgorithmException,InstantiationException,NoSuchMethodException,InvalidKeyException,InvalidAlgorithmParameterException,NoSuchPaddingException,BadPaddingException,InvocationTargetException,IOException,InvalidKeySpecException,IllegalBlockSizeException{String cipherText =AsymmetricEncryptionAlgorithm.RSA_ECB_OAEP_WITH_SHA_256_AND_MGF1_PADDING_1024.encrypt("a",CryptoUtils.RSA_PUBLIC_KEY_FILE_PATH);Assert.assertEquals("a",AsymmetricEncryptionAlgorithm.RSA_ECB_OAEP_WITH_SHA_256_AND_MGF1_PADDING_1024.decrypt(cipherText,CryptoUtils.RSA_PRIVATE_KEY_FILE_PATH));}@TestpublicvoidencryptByPublicKeyFromCert()throwsException{String cipherText =AsymmetricEncryptionAlgorithm.RSA_ECB_OAEP_WITH_SHA_256_AND_MGF1_PADDING_1024.encryptByPublicKeyFromCert("a", certificatePath);Assert.assertEquals("a",AsymmetricEncryptionAlgorithm.RSA_ECB_OAEP_WITH_SHA_256_AND_MGF1_PADDING_1024.decryptByPrivateKeyFromKeyStore(cipherText, keyStorePath));}@TestpublicvoidencryptByPublicKeyFromKeyStore()throwsException{String cipherText =AsymmetricEncryptionAlgorithm.RSA_ECB_OAEP_WITH_SHA_256_AND_MGF1_PADDING_1024.encryptByPublicKeyFromKeyStore("a", keyStorePath);Assert.assertEquals("a",AsymmetricEncryptionAlgorithm.RSA_ECB_OAEP_WITH_SHA_256_AND_MGF1_PADDING_1024.decryptByPrivateKeyFromKeyStore(cipherText, keyStorePath));}}
packagecom.qupeng.crypto.algorithm.oop;importcom.qupeng.crypto.util.CryptoUtils;importcom.qupeng.crypto.util.DigitalCertificationUtils;importsun.misc.BASE64Decoder;importsun.misc.BASE64Encoder;importsun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;importjavax.crypto.BadPaddingException;importjavax.crypto.Cipher;importjavax.crypto.IllegalBlockSizeException;importjavax.crypto.NoSuchPaddingException;importjavax.crypto.spec.OAEPParameterSpec;importjava.io.IOException;importjava.lang.reflect.InvocationTargetException;importjava.nio.file.Path;importjava.security.*;importjava.security.spec.AlgorithmParameterSpec;importjava.security.spec.InvalidKeySpecException;importjava.security.spec.PKCS8EncodedKeySpec;importjava.security.spec.X509EncodedKeySpec;publicenumAsymmetricEncryptionAlgorithm{RSA_ECB_PKCS1_PADDING_1024("RSA","ECB","PKCS1Padding",1024,128,TlsRsaPremasterSecretParameterSpec.class),RSA_ECB_PKCS1_PADDING_2048("RSA","ECB","PKCS1Padding",2048,256,TlsRsaPremasterSecretParameterSpec.class),RSA_ECB_OAEP_WITH_SHA_1_AND_MGF1_PADDING_1024("RSA","ECB","OAEPWithSHA-1AndMGF1Padding",1024,128,OAEPParameterSpec.class),RSA_ECB_OAEP_WITH_SHA_1_AND_MGF1_PADDING_2048("RSA","ECB","OAEPWithSHA-1AndMGF1Padding",2048,256,OAEPParameterSpec.class),RSA_ECB_OAEP_WITH_SHA_256_AND_MGF1_PADDING_1024("RSA","ECB","OAEPWithSHA-256AndMGF1Padding",1024,128,OAEPParameterSpec.class),RSA_ECB_OAEP_WITH_SHA_256_AND_MGF1_PADDING_2048("RSA","ECB","OAEPWithSHA-256AndMGF1Padding",2048,256,OAEPParameterSpec.class);privateString transformation ="";privateString algorithm ="";privateString mode ="";privateString padding ="";privateint secretKeyStrLength =-1;privateint secretKeyBitLength =-1;privateClass<?extendsAlgorithmParameterSpec> algorithmParameterSpecClass;AsymmetricEncryptionAlgorithm(String algorithm,String mode,String padding,int secretKeyBitLength,int secretKeyStrLength,Class<?extendsAlgorithmParameterSpec> algorithmParameterSpecClass){this.algorithm = algorithm;this.mode = mode;this.padding = padding;this.transformation =String.format("%s/%s/%s", algorithm, mode, padding);this.secretKeyStrLength = secretKeyStrLength;this.secretKeyBitLength = secretKeyBitLength;this.algorithmParameterSpecClass = algorithmParameterSpecClass;}// 1 使用秘钥字符串加密publicStringencrypt(String plainText,String secretKeyStr)throwsNoSuchPaddingException,InvalidKeyException,NoSuchAlgorithmException,IllegalBlockSizeException,BadPaddingException,InvalidAlgorithmParameterException,NoSuchMethodException,InstantiationException,IllegalAccessException,InvocationTargetException,InvalidKeySpecException,IOException{returnencrypt(plainText, secretKeyStr,null,null);}// 1 使用秘钥字符串解密publicStringdecrypt(String base64Content,String secretKeyStr)throwsNoSuchPaddingException,NoSuchAlgorithmException,InvalidAlgorithmParameterException,InvalidKeyException,BadPaddingException,IllegalBlockSizeException,NoSuchMethodException,InstantiationException,IllegalAccessException,InvocationTargetException,InvalidKeySpecException,IOException{returndecrypt(base64Content, secretKeyStr,null,null);}// 2 使用随机数种子字符串加密和指定的随机数算法加密publicStringencrypt(String plainText,String randomSeedStr,NumberGenerationAlgorithm ngAlgorithm)throwsNoSuchPaddingException,InvalidKeyException,NoSuchAlgorithmException,IllegalBlockSizeException,BadPaddingException,InvalidAlgorithmParameterException,NoSuchMethodException,InstantiationException,IllegalAccessException,InvocationTargetException,InvalidKeySpecException,IOException{returnencrypt(plainText,null, randomSeedStr, ngAlgorithm);}// 2 使用随机数种子字符串加密和指定的随机数算法解密publicStringdecrypt(String base64Content,String randomSeedStr,NumberGenerationAlgorithm ngAlgorithm)throwsNoSuchPaddingException,NoSuchAlgorithmException,InvalidAlgorithmParameterException,InvalidKeyException,BadPaddingException,IllegalBlockSizeException,NoSuchMethodException,InstantiationException,IllegalAccessException,InvocationTargetException,InvalidKeySpecException,IOException{returndecrypt(base64Content,null, randomSeedStr, ngAlgorithm);}// 3 使用随机数种子字符串加密和默认的随机数算法加密publicStringencryptByKeyGenerator(String plainText,String randomSeedStr)throwsNoSuchPaddingException,InvalidKeyException,NoSuchAlgorithmException,IllegalBlockSizeException,BadPaddingException,InvalidAlgorithmParameterException,NoSuchMethodException,InstantiationException,IllegalAccessException,InvocationTargetException,InvalidKeySpecException,IOException{returnencrypt(plainText,null, randomSeedStr,null);}// 3 使用随机数种子字符串加密和默认的随机数算法解密publicStringdecryptByKeyGenerator(String base64Content,String randomSeedStr)throwsNoSuchPaddingException,NoSuchAlgorithmException,InvalidAlgorithmParameterException,InvalidKeyException,BadPaddingException,IllegalBlockSizeException,NoSuchMethodException,InstantiationException,IllegalAccessException,InvocationTargetException,InvalidKeySpecException,IOException{returndecrypt(base64Content,null, randomSeedStr,null);}// 4 从文件从获取公钥并加密publicStringencrypt(String plainText,Path publicKeyFilePath)throwsNoSuchPaddingException,InvalidKeyException,NoSuchAlgorithmException,IllegalBlockSizeException,BadPaddingException,InvalidAlgorithmParameterException,NoSuchMethodException,InstantiationException,IllegalAccessException,InvocationTargetException,InvalidKeySpecException,IOException{String publicKeyStr =CryptoUtils.readKeyStrFromFile(publicKeyFilePath);returnencrypt(plainText, publicKeyStr,null,null);}// 4 从文件中获取私钥并解密publicStringdecrypt(String base64Content,Path privateKeyFilePath)throwsNoSuchPaddingException,NoSuchAlgorithmException,InvalidAlgorithmParameterException,InvalidKeyException,BadPaddingException,IllegalBlockSizeException,NoSuchMethodException,InstantiationException,IllegalAccessException,InvocationTargetException,InvalidKeySpecException,IOException{String privateKeyStr =CryptoUtils.readKeyStrFromFile(privateKeyFilePath);returndecrypt(base64Content, privateKeyStr,null,null);}// 5 从公钥证书中获取公钥并加密publicStringencryptByPublicKeyFromCert(String plainText,Path publicKeyCertPath)throwsException{PublicKey publicKey =CryptoUtils.getPublicKeyFromCA(publicKeyCertPath,"X.509");returnencrypt(plainText,newBASE64Encoder().encode(publicKey.getEncoded()),newBASE64Encoder().encode(publicKey.getEncoded()),null);}// 6 从文件从获取公钥并加密publicStringencryptByPublicKeyFromKeyStore(String plainText,Path keyStorePath)throwsException{PublicKey publicKey =CryptoUtils.getPublicKeyFromKeyStore(keyStorePath,"testing-keys","123456","PKCS12");returnencrypt(plainText,newBASE64Encoder().encode(publicKey.getEncoded()),null,null);}// 6 从文件中获取私钥并解密publicStringdecryptByPrivateKeyFromKeyStore(String base64Content,Path keyStorePath)throwsException{PrivateKey privateKey =CryptoUtils.getPrivateKeyFromKeyStore(keyStorePath,"testing-keys","123456","PKCS12");;returndecrypt(base64Content,newBASE64Encoder().encode(privateKey.getEncoded()),null,null);}privateStringencrypt(String plainText,String secretKeyStr,String randomSeedStr,NumberGenerationAlgorithm ngAlgorithm)throwsNoSuchPaddingException,NoSuchAlgorithmException,InvalidAlgorithmParameterException,InvalidKeyException,BadPaddingException,IllegalBlockSizeException,InvocationTargetException,NoSuchMethodException,InstantiationException,IllegalAccessException,InvalidKeySpecException,IOException{validateParameters(secretKeyStr);Cipher cipher =Cipher.getInstance(this.transformation);// 根据参数决定使用密钥字符串还是随机数生成密钥Key secretKey =getPublicKey(secretKeyStr, randomSeedStr, ngAlgorithm);// 根据模式决定是否设置向量setAlgorithmParameterSpec(cipher, secretKey,Cipher.ENCRYPT_MODE);// 如果是无填充,需要自行填充byte[] plainTextBytes =setPadding(cipher, plainText);byte[] encrypted = cipher.doFinal(plainTextBytes);String cipherText =newBASE64Encoder().encode(encrypted);System.out.println(String.format("%s(%d) plain text: %s -> cipher text: %s",this.transformation,this.secretKeyBitLength, plainText, cipherText));return cipherText;}privateStringdecrypt(String base64CipherText,String secretKeyStr,String randomSeedStr,NumberGenerationAlgorithm ngAlgorithm)throwsNoSuchPaddingException,NoSuchAlgorithmException,InvalidAlgorithmParameterException,InvalidKeyException,BadPaddingException,IllegalBlockSizeException,InvocationTargetException,NoSuchMethodException,InstantiationException,IllegalAccessException,InvalidKeySpecException,IOException{validateParameters(secretKeyStr);Cipher cipher =Cipher.getInstance(transformation);Key secretKey =getPrivateKey(secretKeyStr, randomSeedStr, ngAlgorithm);setAlgorithmParameterSpec(cipher, secretKey,Cipher.DECRYPT_MODE);byte[] content =newBASE64Decoder().decodeBuffer(base64CipherText);byte[] encrypted = cipher.doFinal(content);String plainText =newString(encrypted).trim();System.out.println(String.format("%s(%d) cipher text: %s -> plain text: %s",this.transformation,this.secretKeyBitLength, base64CipherText, plainText));return plainText;}privatevoidvalidateParameters(String secretKeyStr){}privateKeygetPublicKey(String secretKeyStr,String randomSeedStr,NumberGenerationAlgorithm ngAlgorithm)throwsNoSuchAlgorithmException,InvalidKeySpecException,IOException{Key secretKey;if(null== secretKeyStr || secretKeyStr.isEmpty()){
            secretKey =getPublicKeyByGenerator(randomSeedStr,null== ngAlgorithm ?NumberGenerationAlgorithm.SHA1_PRNG: ngAlgorithm);}else{
            secretKey =getPublicKeyByStr(secretKeyStr);}return secretKey;}privateKeygetPrivateKey(String secretKeyStr,String randomSeedStr,NumberGenerationAlgorithm ngAlgorithm)throwsNoSuchAlgorithmException,InvalidKeySpecException,IOException{Key secretKey =null;if(null== secretKeyStr || secretKeyStr.isEmpty()){
            secretKey =getPrivateKeyByGenerator(randomSeedStr,null== ngAlgorithm ?NumberGenerationAlgorithm.SHA1_PRNG: ngAlgorithm);}else{
            secretKey =getPrivateKeyByStr(secretKeyStr);}return secretKey;}privatebyte[]setPadding(Cipher cipher,String plainText){byte[] plainTextBytes = plainText.getBytes();if("NoPadding".equals(this.padding)){byte[] plainTextBytesNoPadding = plainTextBytes;int blockSize = cipher.getBlockSize();int length = plainTextBytes.length;//计算需填充长度
            length = length +(blockSize -(length % blockSize));
            plainTextBytes =newbyte[length];//填充System.arraycopy(plainTextBytesNoPadding,0, plainTextBytes,0, plainTextBytesNoPadding.length);}return plainTextBytes;}privatevoidsetAlgorithmParameterSpec(Cipher cipher,Key secretKey,int decryptMode)throwsInvalidKeyException,InvalidAlgorithmParameterException{if(OAEPParameterSpec.class==this.algorithmParameterSpecClass){
            cipher.init(decryptMode, secretKey,OAEPParameterSpec.DEFAULT);}else{
            cipher.init(decryptMode, secretKey);}}privateKeygetPublicKeyByStr(String secretKeyStr)throwsNoSuchAlgorithmException,InvalidKeySpecException,IOException{byte[] keyBytes =newBASE64Decoder().decodeBuffer(secretKeyStr);X509EncodedKeySpec encPubKeySpec =newX509EncodedKeySpec(keyBytes);PublicKey publicKey =KeyFactory.getInstance(this.algorithm).generatePublic(encPubKeySpec);return publicKey;}privateKeygetPrivateKeyByStr(String secretKeyStr)throwsNoSuchAlgorithmException,InvalidKeySpecException,IOException{byte[] keyBytes =newBASE64Decoder().decodeBuffer(secretKeyStr);PKCS8EncodedKeySpec encPriKeySpec =newPKCS8EncodedKeySpec(keyBytes);PrivateKey privateKey =KeyFactory.getInstance(this.algorithm).generatePrivate(encPriKeySpec);return privateKey;}privateKeygetPublicKeyByGenerator(String randomSeedStr,NumberGenerationAlgorithm ngAlgorithm)throwsNoSuchAlgorithmException{returngetKeyPair(randomSeedStr, ngAlgorithm).getPublic();}privateKeygetPrivateKeyByGenerator(String randomSeedStr,NumberGenerationAlgorithm ngAlgorithm)throwsNoSuchAlgorithmException{returngetKeyPair(randomSeedStr, ngAlgorithm).getPrivate();}privateKeyPairgetKeyPair(String randomSeedStr,NumberGenerationAlgorithm ngAlgorithm)throwsNoSuchAlgorithmException{KeyPairGenerator keyPairGenerator  =KeyPairGenerator.getInstance(this.algorithm);SecureRandom random =SecureRandom.getInstance(ngAlgorithm.getAlgorithmName());
        random.setSeed(randomSeedStr.getBytes());
        keyPairGenerator.initialize(this.secretKeyBitLength, random);KeyPair keyPair = keyPairGenerator.generateKeyPair();try{CryptoUtils.writeKeyPairToFile(keyPair,this.algorithm);}catch(IOException e){
            e.printStackTrace();}return keyPair;}}
packagecom.qupeng.crypto.util;importcom.qupeng.crypto.algorithm.oop.NumberGenerationAlgorithm;importorg.apache.commons.codec.DecoderException;importorg.apache.commons.codec.binary.Hex;importorg.bouncycastle.jce.provider.BouncyCastleProvider;importsun.misc.BASE64Decoder;importsun.misc.BASE64Encoder;importjavax.crypto.*;importjavax.crypto.spec.SecretKeySpec;importjava.io.FileInputStream;importjava.io.IOException;importjava.nio.ByteBuffer;importjava.nio.channels.FileChannel;importjava.nio.file.Files;importjava.nio.file.Path;importjava.nio.file.Paths;importjava.nio.file.StandardOpenOption;importjava.security.*;importjava.security.cert.Certificate;importjava.security.cert.CertificateFactory;importjava.security.spec.InvalidKeySpecException;importjava.security.spec.PKCS8EncodedKeySpec;importjava.security.spec.X509EncodedKeySpec;importjava.util.ArrayList;importjava.util.Arrays;importjava.util.Comparator;importjava.util.Map;importjava.util.stream.Collectors;publicclassCryptoUtils{publicfinalstaticPathRSA_PUBLIC_KEY_FILE_PATH=Paths.get("C:","Users","Administrator","IdeaProjects","javasedemo","src","main","resources","rsa-public-key.txt");publicfinalstaticPathRSA_PRIVATE_KEY_FILE_PATH=Paths.get("C:","Users","Administrator","IdeaProjects","javasedemo","src","main","resources","rsa-private-key.txt");publicfinalstaticPathDSA_PUBLIC_KEY_FILE_PATH=Paths.get("C:","Users","Administrator","IdeaProjects","javasedemo","src","main","resources","dsa-public-key.txt");publicfinalstaticPathDSA_PRIVATE_KEY_FILE_PATH=Paths.get("C:","Users","Administrator","IdeaProjects","javasedemo","src","main","resources","dsa-private-key.txt");static{Security.addProvider(newBouncyCastleProvider());}publicstaticvoidprintAllSecurityProviders(){for(Provider provider :Security.getProviders()){System.out.println("Provider: "+ provider.getName()+" (ver "+ provider.getVersion()+")");}}publicstaticvoidprintAllAlgorithmsOfProviders(){for(Provider provider :Security.getProviders()){System.out.println("Provider: "+ provider.getName()+" (ver "+ provider.getVersion()+")");System.out.print("  Algorithms: ");ArrayList<String> algos =newArrayList<String>();for(Provider.Service service : provider.getServices()){
                algos.add(String.format("%s (%s)", service.getAlgorithm(), service.getType()));}java.util.Collections.sort(algos);String algorsStr = algos.toString();
            algorsStr = algorsStr.substring(1, algorsStr.length()-1);System.out.println(algorsStr);System.out.println();}}publicstaticStringprintAllSecurityProvidersInMdTable(){StringBuilder stringBuilder =newStringBuilder();
        stringBuilder.append("Provider Name|Provider Version|Algorithm Type|Algorithm Name\r\n");
        stringBuilder.append("|:-|:-|:-|:-\r\n");Map<String,Map<String,String>> providers2Algorithms =Arrays.stream(Security.getProviders()).collect(Collectors.toMap(provider -> provider.getName()+"@"+ provider.getVersion(), provider -> provider.getServices().stream().collect(Collectors.toMap(service -> service.getType(), service -> service.getAlgorithm(),(algorithm1, algorithm2)-> algorithm1 +"@"+ algorithm2))));
        providers2Algorithms.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getKey)).forEachOrdered(entryProvider ->{String[] provider = entryProvider.getKey().split("@");Map<String,String> algoType2AlgoName = entryProvider.getValue();int[] rowNumber ={0};
            algoType2AlgoName.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getKey)).forEachOrdered(entryAlgorithm ->{StringBuilder algorithmCellStr =newStringBuilder();int[] numberOfAlgorithm ={1};Arrays.stream(entryAlgorithm.getValue().split("@")).sorted(String::compareTo).forEachOrdered(algorithm ->{
                    algorithmCellStr.append(algorithm);if(0== numberOfAlgorithm[0]%1){
                        algorithmCellStr.append("<br>");}
                    numberOfAlgorithm[0]++;});

                stringBuilder.append(String.format("|%s|%s|%s|%s\r\n",0== rowNumber[0]? provider[0]:"",0== rowNumber[0]? provider[1]:"", entryAlgorithm.getKey(), algorithmCellStr.toString()));
                rowNumber[0]++;});});return stringBuilder.toString();}publicstaticvoidwriteKeyPairToFile(KeyPair keyPair,String algorithm)throwsIOException{writeKeyPairToFile(keyPair,"DSA".equalsIgnoreCase(algorithm)?DSA_PUBLIC_KEY_FILE_PATH:RSA_PUBLIC_KEY_FILE_PATH,"DSA".equalsIgnoreCase(algorithm)?DSA_PRIVATE_KEY_FILE_PATH:RSA_PRIVATE_KEY_FILE_PATH);}publicstaticvoidwriteKeyPairToFile(KeyPair keyPair,Path publicKeyFilePath,Path privateKeyFilePath)throwsIOException{writeKeyToFile(keyPair.getPublic(), publicKeyFilePath);writeKeyToFile(keyPair.getPrivate(), privateKeyFilePath);}publicstaticStringreadPublicKeyFromFile(String algorithm)throwsIOException{returnreadKeyStrFromFile("DSA".equalsIgnoreCase(algorithm)?DSA_PUBLIC_KEY_FILE_PATH:RSA_PUBLIC_KEY_FILE_PATH);}publicstaticStringreadPrivateKeyFromFile(String algorithm)throwsIOException{returnreadKeyStrFromFile("DSA".equalsIgnoreCase(algorithm)?DSA_PRIVATE_KEY_FILE_PATH:RSA_PRIVATE_KEY_FILE_PATH);}publicstaticStringreadKeyStrFromFile(Path keyFilePath)throwsIOException{try(FileChannel keyFileChannel =FileChannel.open(keyFilePath,StandardOpenOption.READ)){byte[] bytes =newbyte[0];ByteBuffer byteBuffer =ByteBuffer.allocate(128);int readCount = keyFileChannel.read(byteBuffer);while(0< readCount){
                byteBuffer.flip();int length = bytes.length;
                bytes =Arrays.copyOf(bytes, bytes.length + readCount);System.arraycopy(byteBuffer.array(),0, bytes, length, readCount);
                byteBuffer.clear();
                readCount = keyFileChannel.read(byteBuffer);}String keyStr =newString(bytes);return keyStr;}}publicstaticvoidwriteKeyToFile(Key key,Path filePath)throwsIOException{byte[] keyBytes = key.getEncoded();String keyStr =newBASE64Encoder().encode(keyBytes);if(Files.notExists(filePath)){Files.createFile(filePath);}try(FileChannel keyFileChannel =FileChannel.open(filePath,StandardOpenOption.WRITE)){ByteBuffer byteBuffer =ByteBuffer.allocate(keyStr.getBytes().length);
            byteBuffer.put(keyStr.getBytes());
            byteBuffer.flip();
            keyFileChannel.write(byteBuffer);}}publicstaticPublicKeygetPublicKeyByStr(String algorithm,String secretKeyStr)throwsNoSuchAlgorithmException,InvalidKeySpecException,IOException{byte[] keyBytes =newBASE64Decoder().decodeBuffer(secretKeyStr);X509EncodedKeySpec encPubKeySpec =newX509EncodedKeySpec(keyBytes);PublicKey publicKey =KeyFactory.getInstance(algorithm).generatePublic(encPubKeySpec);return publicKey;}publicstaticPrivateKeygetPrivateKeyByStr(String algorithm,String secretKeyStr)throwsNoSuchAlgorithmException,InvalidKeySpecException,IOException{byte[] keyBytes =newBASE64Decoder().decodeBuffer(secretKeyStr);PKCS8EncodedKeySpec encPriKeySpec =newPKCS8EncodedKeySpec(keyBytes);PrivateKey privateKey =KeyFactory.getInstance(algorithm).generatePrivate(encPriKeySpec);return privateKey;}publicstaticKeyPairgetKeyPair(String algorithm,int secretKeyBitLength,String randomSeedStr,NumberGenerationAlgorithm ngAlgorithm)throwsNoSuchAlgorithmException{KeyPairGenerator keyPairGenerator  =KeyPairGenerator.getInstance(algorithm);SecureRandom random =SecureRandom.getInstance(ngAlgorithm.getAlgorithmName());
        random.setSeed(randomSeedStr.getBytes());
        keyPairGenerator.initialize(secretKeyBitLength, random);return keyPairGenerator.generateKeyPair();}publicstaticStringwrapSecretKey(String keyString)throwsException{KeyGenerator keyGenerator =KeyGenerator.getInstance("AES");
        keyGenerator.init(128,newSecureRandom("123456".getBytes()));SecretKey secretKey = keyGenerator.generateKey();Cipher cipher =Cipher.getInstance("AES");
        cipher.init(Cipher.WRAP_MODE, secretKey);SecretKeySpec key =newSecretKeySpec(keyString.getBytes(),"AES");byte[] bytes = cipher.wrap(key);returnHex.encodeHexString(bytes);}publicstaticStringunwrapSecretKey(String keyString)throwsException{byte[] rawKey =Hex.decodeHex(keyString);KeyGenerator keyGenerator =KeyGenerator.getInstance("AES");
        keyGenerator.init(128,newSecureRandom("123456".getBytes()));SecretKey secretKey = keyGenerator.generateKey();Cipher cipher =Cipher.getInstance("AES");
        cipher.init(Cipher.UNWRAP_MODE, secretKey);SecretKey key =(SecretKey) cipher.unwrap(rawKey,"AES",Cipher.SECRET_KEY);returnnewString(key.getEncoded());}publicstaticStringwrapPrivateKey()throwsNoSuchAlgorithmException,NoSuchPaddingException,InvalidKeyException,IllegalBlockSizeException{SecureRandom secureRandom =SecureRandom.getInstance(NumberGenerationAlgorithm.SHA1_PRNG.getAlgorithmName());
        secureRandom.setSeed("12345".getBytes());KeyGenerator keyGenerator =KeyGenerator.getInstance("AES");
        keyGenerator.init(128, secureRandom);SecretKey secretKey = keyGenerator.generateKey();Cipher cipher =Cipher.getInstance("AES");
        cipher.init(Cipher.WRAP_MODE, secretKey, secureRandom);KeyPairGenerator keyPairGenerator =KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(1024, secureRandom);KeyPair keyPair = keyPairGenerator.generateKeyPair();System.out.println(Hex.encodeHexString(keyPair.getPrivate().getEncoded()));byte[] keyBytes = cipher.wrap(keyPair.getPrivate());String wrappedKeyStr =Hex.encodeHexString(keyBytes);System.out.println(wrappedKeyStr);return wrappedKeyStr;}publicstaticStringunwrapPrivateKey(String keyStr)throwsNoSuchAlgorithmException,NoSuchPaddingException,InvalidKeyException,IllegalBlockSizeException,DecoderException{SecureRandom secureRandom =SecureRandom.getInstance(NumberGenerationAlgorithm.SHA1_PRNG.getAlgorithmName());
        secureRandom.setSeed("12345".getBytes());KeyGenerator keyGenerator =KeyGenerator.getInstance("AES");
        keyGenerator.init(128, secureRandom);SecretKey secretKey = keyGenerator.generateKey();Cipher cipher =Cipher.getInstance("AES");
        cipher.init(Cipher.UNWRAP_MODE, secretKey, secureRandom);byte[] keyBytes =Hex.decodeHex(keyStr);PrivateKey privateKey =(PrivateKey) cipher.unwrap(keyBytes,"RSA",Cipher.PRIVATE_KEY);returnHex.encodeHexString(privateKey.getEncoded());}publicstaticPublicKeygetPublicKeyFromCA(Path certificatePath,String certificationType)throwsException{CertificateFactory certificateFactory =CertificateFactory.getInstance(certificationType);try(FileInputStream in =newFileInputStream(certificatePath.toFile())){Certificate certificate = certificateFactory.generateCertificate(in);return certificate.getPublicKey();}}publicstaticPublicKeygetPublicKeyFromKeyStore(Path keyStorePath,String alias,String password,String keyStoreType)throwsException{try(FileInputStream is =newFileInputStream(keyStorePath.toFile())){KeyStore keyStore =KeyStore.getInstance(keyStoreType);
            keyStore.load(is, password.toCharArray());return keyStore.getCertificate(alias).getPublicKey();}}publicstaticPrivateKeygetPrivateKeyFromKeyStore(Path keyStorePath,String alias,String password,String keyStoreType)throwsException{try(FileInputStream is =newFileInputStream(keyStorePath.toFile())){KeyStore keyStore =KeyStore.getInstance(keyStoreType);
            keyStore.load(is, password.toCharArray());return(PrivateKey) keyStore.getKey(alias, password.toCharArray());}}}

本文转载自: https://blog.csdn.net/yunyun1886358/article/details/128631303
版权归原作者 yunyun1886358 所有, 如有侵权,请联系我们删除。

“Java加解密(四)非对称加密”的评论:

还没有评论