赞
踩
非对称加密算法需要两个密钥:公开密钥(publickey:简称公钥)和私有密钥(privatekey:简称私钥)。公钥与私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。
由于安全性较好,并且密钥可以公开,无交换过程泄密的风险,因此非对此密钥算法被广泛使用,比如SSH、HTTPS、电子证书、数字签名、加密通讯等领域。
公钥既可以进行加密,也可以解密,私钥也是一样,用于支持不同场景:
1977年,三位数学家Rivest、Shamir 和 Adleman 设计了一种算法,可以实现非对称加密。这种算法用他们三个人的名字命名,叫做RSA算法,RSA算法从被发明至今一直是最广为使用的"非对称加密算法"。其他场景的算法还有Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)。
JDK8原生算法列表,可参第一篇博文: https://blog.csdn.net/yunyun1886358/article/details/128592503#311_JDK_Provider_63
Bouncy Castle算法列表,可参第一篇博文:
https://editor.csdn.net/md/?articleId=128592503#323_Bouncy_Castle_Provider_568
下面的代码将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
package com.qupeng.crypto.algorithm.oop; import com.qupeng.crypto.util.CryptoUtils; import com.qupeng.crypto.util.DigitalCertificationUtilsTest; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import javax.crypto.BadPaddingException; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.nio.file.Path; import java.nio.file.Paths; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidKeySpecException; public class AsymmetricEncryptionAlgorithmTest { private static Path keyStorePath; private static Path certificatePath; @BeforeClass public static void setUp() throws Exception { keyStorePath = Paths.get(DigitalCertificationUtilsTest.class.getClassLoader().getResource("testing-keystore.p12").toURI()); certificatePath = Paths.get(DigitalCertificationUtilsTest.class.getClassLoader().getResource("testing-ca.cer").toURI()); } @Test public void encryptByRandomSeed() throws Exception { // RSA 1024 bits secret String 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)); } @Test public void encryptByPublicKeyStr() throws IllegalAccessException, 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=")); } @Test public void encryptByPublicKeyFromFile() throws IllegalAccessException, 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)); } @Test public void encryptByPublicKeyFromCert() throws Exception { 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)); } @Test public void encryptByPublicKeyFromKeyStore() throws Exception { 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)); } }
package com.qupeng.crypto.algorithm.oop; import com.qupeng.crypto.util.CryptoUtils; import com.qupeng.crypto.util.DigitalCertificationUtils; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.OAEPParameterSpec; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.nio.file.Path; import java.security.*; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; public enum AsymmetricEncryptionAlgorithm { 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); private String transformation = ""; private String algorithm = ""; private String mode = ""; private String padding = ""; private int secretKeyStrLength = -1; private int secretKeyBitLength = -1; private Class<? extends AlgorithmParameterSpec> algorithmParameterSpecClass; AsymmetricEncryptionAlgorithm(String algorithm, String mode, String padding, int secretKeyBitLength, int secretKeyStrLength, Class<? extends AlgorithmParameterSpec> 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 使用秘钥字符串加密 public String encrypt(String plainText, String secretKeyStr) throws NoSuchPaddingException, InvalidKeyException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, InvalidKeySpecException, IOException { return encrypt(plainText, secretKeyStr, null, null); } // 1 使用秘钥字符串解密 public String decrypt(String base64Content, String secretKeyStr) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, InvalidKeySpecException, IOException { return decrypt(base64Content, secretKeyStr, null, null); } // 2 使用随机数种子字符串加密和指定的随机数算法加密 public String encrypt(String plainText, String randomSeedStr, NumberGenerationAlgorithm ngAlgorithm) throws NoSuchPaddingException, InvalidKeyException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, InvalidKeySpecException, IOException { return encrypt(plainText, null, randomSeedStr, ngAlgorithm); } // 2 使用随机数种子字符串加密和指定的随机数算法解密 public String decrypt(String base64Content, String randomSeedStr, NumberGenerationAlgorithm ngAlgorithm) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, InvalidKeySpecException, IOException { return decrypt(base64Content, null, randomSeedStr, ngAlgorithm); } // 3 使用随机数种子字符串加密和默认的随机数算法加密 public String encryptByKeyGenerator(String plainText, String randomSeedStr) throws NoSuchPaddingException, InvalidKeyException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, InvalidKeySpecException, IOException { return encrypt(plainText, null, randomSeedStr, null); } // 3 使用随机数种子字符串加密和默认的随机数算法解密 public String decryptByKeyGenerator(String base64Content, String randomSeedStr) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, InvalidKeySpecException, IOException { return decrypt(base64Content, null, randomSeedStr, null); } // 4 从文件从获取公钥并加密 public String encrypt(String plainText, Path publicKeyFilePath) throws NoSuchPaddingException, InvalidKeyException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, InvalidKeySpecException, IOException { String publicKeyStr = CryptoUtils.readKeyStrFromFile(publicKeyFilePath); return encrypt(plainText, publicKeyStr, null, null); } // 4 从文件中获取私钥并解密 public String decrypt(String base64Content, Path privateKeyFilePath) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, InvalidKeySpecException, IOException { String privateKeyStr = CryptoUtils.readKeyStrFromFile(privateKeyFilePath); return decrypt(base64Content, privateKeyStr, null, null); } // 5 从公钥证书中获取公钥并加密 public String encryptByPublicKeyFromCert(String plainText, Path publicKeyCertPath) throws Exception { PublicKey publicKey = CryptoUtils.getPublicKeyFromCA(publicKeyCertPath, "X.509"); return encrypt(plainText, new BASE64Encoder().encode(publicKey.getEncoded()), new BASE64Encoder().encode(publicKey.getEncoded()), null); } // 6 从文件从获取公钥并加密 public String encryptByPublicKeyFromKeyStore(String plainText, Path keyStorePath) throws Exception { PublicKey publicKey = CryptoUtils.getPublicKeyFromKeyStore(keyStorePath, "testing-keys", "123456", "PKCS12"); return encrypt(plainText, new BASE64Encoder().encode(publicKey.getEncoded()), null, null); } // 6 从文件中获取私钥并解密 public String decryptByPrivateKeyFromKeyStore(String base64Content, Path keyStorePath) throws Exception { PrivateKey privateKey = CryptoUtils.getPrivateKeyFromKeyStore(keyStorePath, "testing-keys", "123456", "PKCS12");; return decrypt(base64Content, new BASE64Encoder().encode(privateKey.getEncoded()), null, null); } private String encrypt(String plainText, String secretKeyStr, String randomSeedStr, NumberGenerationAlgorithm ngAlgorithm) throws NoSuchPaddingException, 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 = new BASE64Encoder().encode(encrypted); System.out.println(String.format("%s(%d) plain text: %s -> cipher text: %s", this.transformation, this.secretKeyBitLength, plainText, cipherText)); return cipherText; } private String decrypt(String base64CipherText, String secretKeyStr, String randomSeedStr, NumberGenerationAlgorithm ngAlgorithm) throws NoSuchPaddingException, 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 = new BASE64Decoder().decodeBuffer(base64CipherText); byte[] encrypted = cipher.doFinal(content); String plainText = new String(encrypted).trim(); System.out.println(String.format("%s(%d) cipher text: %s -> plain text: %s", this.transformation, this.secretKeyBitLength, base64CipherText, plainText)); return plainText; } private void validateParameters(String secretKeyStr) { } private Key getPublicKey(String secretKeyStr, String randomSeedStr, NumberGenerationAlgorithm ngAlgorithm) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException { Key secretKey; if (null == secretKeyStr || secretKeyStr.isEmpty()) { secretKey = getPublicKeyByGenerator(randomSeedStr, null == ngAlgorithm ? NumberGenerationAlgorithm.SHA1_PRNG : ngAlgorithm); } else { secretKey = getPublicKeyByStr(secretKeyStr); } return secretKey; } private Key getPrivateKey(String secretKeyStr, String randomSeedStr, NumberGenerationAlgorithm ngAlgorithm) throws NoSuchAlgorithmException, 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; } private byte[] 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 = new byte[length]; //填充 System.arraycopy(plainTextBytesNoPadding, 0, plainTextBytes, 0, plainTextBytesNoPadding.length); } return plainTextBytes; } private void setAlgorithmParameterSpec(Cipher cipher, Key secretKey, int decryptMode) throws InvalidKeyException, InvalidAlgorithmParameterException { if (OAEPParameterSpec.class == this.algorithmParameterSpecClass) { cipher.init(decryptMode, secretKey, OAEPParameterSpec.DEFAULT); } else { cipher.init(decryptMode, secretKey); } } private Key getPublicKeyByStr(String secretKeyStr) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException { byte[] keyBytes = new BASE64Decoder().decodeBuffer(secretKeyStr); X509EncodedKeySpec encPubKeySpec = new X509EncodedKeySpec(keyBytes); PublicKey publicKey = KeyFactory.getInstance(this.algorithm).generatePublic(encPubKeySpec); return publicKey; } private Key getPrivateKeyByStr(String secretKeyStr) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException { byte[] keyBytes = new BASE64Decoder().decodeBuffer(secretKeyStr); PKCS8EncodedKeySpec encPriKeySpec = new PKCS8EncodedKeySpec(keyBytes); PrivateKey privateKey = KeyFactory.getInstance(this.algorithm).generatePrivate(encPriKeySpec); return privateKey; } private Key getPublicKeyByGenerator(String randomSeedStr, NumberGenerationAlgorithm ngAlgorithm) throws NoSuchAlgorithmException { return getKeyPair(randomSeedStr, ngAlgorithm).getPublic(); } private Key getPrivateKeyByGenerator(String randomSeedStr, NumberGenerationAlgorithm ngAlgorithm) throws NoSuchAlgorithmException { return getKeyPair(randomSeedStr, ngAlgorithm).getPrivate(); } private KeyPair getKeyPair(String randomSeedStr, NumberGenerationAlgorithm ngAlgorithm) throws NoSuchAlgorithmException { 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; } }
package com.qupeng.crypto.util; import com.qupeng.crypto.algorithm.oop.NumberGenerationAlgorithm; import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.binary.Hex; import org.bouncycastle.jce.provider.BouncyCastleProvider; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; import javax.crypto.*; import javax.crypto.spec.SecretKeySpec; import java.io.FileInputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.security.*; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.Map; import java.util.stream.Collectors; public class CryptoUtils { public final static Path RSA_PUBLIC_KEY_FILE_PATH = Paths.get("C:", "Users", "Administrator", "IdeaProjects", "javasedemo", "src", "main", "resources", "rsa-public-key.txt"); public final static Path RSA_PRIVATE_KEY_FILE_PATH = Paths.get("C:", "Users", "Administrator", "IdeaProjects", "javasedemo", "src", "main", "resources", "rsa-private-key.txt"); public final static Path DSA_PUBLIC_KEY_FILE_PATH = Paths.get("C:", "Users", "Administrator", "IdeaProjects", "javasedemo", "src", "main", "resources", "dsa-public-key.txt"); public final static Path DSA_PRIVATE_KEY_FILE_PATH = Paths.get("C:", "Users", "Administrator", "IdeaProjects", "javasedemo", "src", "main", "resources", "dsa-private-key.txt"); static { Security.addProvider(new BouncyCastleProvider()); } public static void printAllSecurityProviders() { for (Provider provider : Security.getProviders()) { System.out.println("Provider: " + provider.getName() + " (ver " + provider.getVersion() + ")"); } } public static void printAllAlgorithmsOfProviders() { for (Provider provider : Security.getProviders()) { System.out.println("Provider: " + provider.getName() + " (ver " + provider.getVersion() + ")"); System.out.print(" Algorithms: "); ArrayList<String> algos = new ArrayList<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(); } } public static String printAllSecurityProvidersInMdTable() { StringBuilder stringBuilder = new StringBuilder(); 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 = new StringBuilder(); 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(); } public static void writeKeyPairToFile(KeyPair keyPair, String algorithm) throws IOException { 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); } public static void writeKeyPairToFile(KeyPair keyPair, Path publicKeyFilePath, Path privateKeyFilePath) throws IOException { writeKeyToFile(keyPair.getPublic(), publicKeyFilePath); writeKeyToFile(keyPair.getPrivate(), privateKeyFilePath); } public static String readPublicKeyFromFile(String algorithm) throws IOException { return readKeyStrFromFile("DSA".equalsIgnoreCase(algorithm) ? DSA_PUBLIC_KEY_FILE_PATH : RSA_PUBLIC_KEY_FILE_PATH); } public static String readPrivateKeyFromFile(String algorithm) throws IOException { return readKeyStrFromFile("DSA".equalsIgnoreCase(algorithm) ? DSA_PRIVATE_KEY_FILE_PATH : RSA_PRIVATE_KEY_FILE_PATH); } public static String readKeyStrFromFile(Path keyFilePath) throws IOException { try (FileChannel keyFileChannel = FileChannel.open(keyFilePath, StandardOpenOption.READ)) { byte[] bytes = new byte[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 = new String(bytes); return keyStr; } } public static void writeKeyToFile(Key key, Path filePath) throws IOException { byte[] keyBytes = key.getEncoded(); String keyStr = new BASE64Encoder().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); } } public static PublicKey getPublicKeyByStr(String algorithm, String secretKeyStr) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException { byte[] keyBytes = new BASE64Decoder().decodeBuffer(secretKeyStr); X509EncodedKeySpec encPubKeySpec = new X509EncodedKeySpec(keyBytes); PublicKey publicKey = KeyFactory.getInstance(algorithm).generatePublic(encPubKeySpec); return publicKey; } public static PrivateKey getPrivateKeyByStr(String algorithm, String secretKeyStr) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException { byte[] keyBytes = new BASE64Decoder().decodeBuffer(secretKeyStr); PKCS8EncodedKeySpec encPriKeySpec = new PKCS8EncodedKeySpec(keyBytes); PrivateKey privateKey = KeyFactory.getInstance(algorithm).generatePrivate(encPriKeySpec); return privateKey; } public static KeyPair getKeyPair(String algorithm, int secretKeyBitLength, String randomSeedStr, NumberGenerationAlgorithm ngAlgorithm) throws NoSuchAlgorithmException { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm); SecureRandom random = SecureRandom.getInstance(ngAlgorithm.getAlgorithmName()); random.setSeed(randomSeedStr.getBytes()); keyPairGenerator.initialize(secretKeyBitLength, random); return keyPairGenerator.generateKeyPair(); } public static String wrapSecretKey(String keyString) throws Exception { KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); keyGenerator.init(128, new SecureRandom("123456".getBytes())); SecretKey secretKey = keyGenerator.generateKey(); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.WRAP_MODE, secretKey); SecretKeySpec key = new SecretKeySpec(keyString.getBytes(), "AES"); byte[] bytes = cipher.wrap(key); return Hex.encodeHexString(bytes); } public static String unwrapSecretKey(String keyString) throws Exception { byte[] rawKey = Hex.decodeHex(keyString); KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); keyGenerator.init(128, new SecureRandom("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); return new String(key.getEncoded()); } public static String wrapPrivateKey() throws NoSuchAlgorithmException, 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; } public static String unwrapPrivateKey(String keyStr) throws NoSuchAlgorithmException, 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); return Hex.encodeHexString(privateKey.getEncoded()); } public static PublicKey getPublicKeyFromCA(Path certificatePath, String certificationType) throws Exception { CertificateFactory certificateFactory = CertificateFactory.getInstance(certificationType); try (FileInputStream in = new FileInputStream(certificatePath.toFile())) { Certificate certificate = certificateFactory.generateCertificate(in); return certificate.getPublicKey(); } } public static PublicKey getPublicKeyFromKeyStore(Path keyStorePath, String alias, String password, String keyStoreType) throws Exception { try (FileInputStream is = new FileInputStream(keyStorePath.toFile())) { KeyStore keyStore = KeyStore.getInstance(keyStoreType); keyStore.load(is, password.toCharArray()); return keyStore.getCertificate(alias).getPublicKey(); } } public static PrivateKey getPrivateKeyFromKeyStore(Path keyStorePath, String alias, String password, String keyStoreType) throws Exception { try (FileInputStream is = new FileInputStream(keyStorePath.toFile())) { KeyStore keyStore = KeyStore.getInstance(keyStoreType); keyStore.load(is, password.toCharArray()); return (PrivateKey) keyStore.getKey(alias, password.toCharArray()); } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。