Encryption Java-如何修复InvalidKeyException:错误的算法类型-RSA
我有一个私人JKS文件和密码文件。我看到了互联网,写了一个java程序,它会把私钥打印成字符串 类似地,我得到了一个扩展名为.cer的公钥文件。同样,我也以字符串的形式打印出了这个文件的内容 我的想法是写一个java程序,它有两种加密和解密方法。但当我尝试使用加密和解密函数时,我看到了InvalidKeyException:错误的算法类型。我从jks文件中打印出了算法,并将其视为RSA。在公共证书中,算法打印为SHA1 with RSA 这是我的节目Encryption Java-如何修复InvalidKeyException:错误的算法类型-RSA,encryption,rsa,public-key,key,java,Encryption,Rsa,Public Key,Key,Java,我有一个私人JKS文件和密码文件。我看到了互联网,写了一个java程序,它会把私钥打印成字符串 类似地,我得到了一个扩展名为.cer的公钥文件。同样,我也以字符串的形式打印出了这个文件的内容 我的想法是写一个java程序,它有两种加密和解密方法。但当我尝试使用加密和解密函数时,我看到了InvalidKeyException:错误的算法类型。我从jks文件中打印出了算法,并将其视为RSA。在公共证书中,算法打印为SHA1 with RSA 这是我的节目 import java.io.ByteArr
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import org.apache.commons.codec.binary.Base64;
public class ExtractKeys {
private static String privateKeyalgorithm = "";
private static String publicKeyAlgorithm = "";
public static void main(String args[]) throws Exception {
String publicCertificate = "C:\\QA\\keys\\sis.cer";
String privateKeyStore = "C:\\QA\\keys\\sis.jks";
String privateKeyStorePassword = "sis";
String alias = "sis";
String aliasPassword = "sis";
ExtractKeys myep = new ExtractKeys();
myep.printPrivateKey(privateKeyStore, privateKeyStorePassword, alias, aliasPassword);
myep.printPublicKey(publicCertificate);
}
public String printPublicKey(String source) throws Exception {
X509Certificate cert = null;
InputStream fis = null;
ByteArrayInputStream bais = null;
Base64 encoder = new Base64(64);
fis = new FileInputStream(source);
byte value[] = new byte[fis.available()];
fis.read(value);
bais = new ByteArrayInputStream(value);
java.security.cert.CertificateFactory cf = java.security.cert.CertificateFactory.getInstance("X.509");
cert = (X509Certificate) cf.generateCertificate(bais);
String cert_begin = "-----BEGIN CERTIFICATE-----\n";
String end_cert = "-----END CERTIFICATE-----";
publicKeyAlgorithm = cert.getSigAlgName();
byte[] derCert = cert.getEncoded();
String pemCertPre = new String(encoder.encode(derCert));
String pemCert = cert_begin + pemCertPre + end_cert;
System.out.println(pemCert);
System.out.println(publicKeyAlgorithm);
return pemCert;
}
public String printPrivateKey(String fileName, String keystorepass, String aliasName, String aliaspass) throws Exception {
KeyStore ks = KeyStore.getInstance("JKS");
Base64 encoder = new Base64(64);
char[] keyStorePassPhrase = keystorepass.toCharArray();
File certificateFile = new File(fileName);
ks.load(new FileInputStream(certificateFile), keyStorePassPhrase);
char[] aliasPassPhrase = aliaspass.toCharArray();
KeyPair kp = getPrivateKey(ks, aliasName, aliasPassPhrase);
PrivateKey privKey = kp.getPrivate();
privateKeyalgorithm = privKey.getAlgorithm();
String b64 = encoder.encodeAsString(privKey.getEncoded());
System.out.println("-----BEGIN PRIVATE KEY-----");
System.out.println(b64);
System.out.println("-----END PRIVATE KEY-----");
System.out.println(privateKeyalgorithm);
return b64;
}
private KeyPair getPrivateKey(KeyStore keystore, String alias, char[] password) {
try {
// Get private key
Key key = keystore.getKey(alias, password);
if (key instanceof PrivateKey) {
// Get certificate of public key
Certificate cert = keystore.getCertificate(alias);
// Get public key
PublicKey publicKey = cert.getPublicKey();
// Return a key pair
return new KeyPair(publicKey, (PrivateKey) key);
}
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
}
return null;
}
public String returnPrivateKeyAlgo() {
return privateKeyalgorithm;
}
public String returnPublicKeyAlgo() {
return publicKeyAlgorithm;
}
输出是公钥、私钥及其算法的字符串
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCZehr60/61+4ao
8Bigkamzt3RJZcY9ggE4YuQ1ALY8pDXARDQ3OqPohySw4y+Ebrk4y/Rwzm21mhaU
jC33BNSNUetRAgBDU+/nT3/gRZdIeJRfFdiDtl/Ms2LYxo41nYTeGJEqoW3fivI2
cUG/tDKSPjaoGwnz/kVNIsZXJEcZCAfdIg1UH0wBeQ5qLR4rsseE0I7vVAfvDsMl
-----END PRIVATE KEY-----
RSA
-----BEGIN CERTIFICATE-----
MIIGiTCCBXGgAwIBAgIKYMbAHgAAAAUgKzANBgkqhkiG9w0BAQUFADB5MRMwEQYK
CZImiZPyLGQBGRYDY29tMRYwFAYKCZImiZPyLGQBGRYGc2Nod2FiMRYwFAYKCZIm
-----END CERTIFICATE-----
SHA1withRSA
现在我将公钥和私钥作为字符串值。以及他们的算法
接下来我编写了另一个示例程序,其中有两个方法。加密和解密也接受这些密钥
所以理想情况下,我会将公钥传递给加密方法,将私钥传递给解密方法
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import **.CryptoService;
import **.CryptoServiceException;
public class CryptoServiceImpl implements CryptoService {
public byte[] encrypt(byte[] data, String key) throws Exception {
try {
Cipher cipher = Cipher.getInstance("RSA");
Base64 decoder = new Base64(64);
// decode the base64 encoded string
byte[] decodedKey = decoder.decode(key);
// rebuild key using SecretKeySpec
final SecretKeySpec originalKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, "RSA");
cipher.init(Cipher.ENCRYPT_MODE, originalKey);
final String encryptedString = Base64.encodeBase64String(cipher.doFinal(data));
return encryptedString.getBytes();
} catch (Exception e) {
throw new CryptoServiceException("Cannot encrypt data using key '", e);
}
}
public byte[] decrypt(byte[] data, String key) throws Exception {
try {
Cipher cipher = Cipher.getInstance("RSA");
Base64 decoder = new Base64(64);
// decode the base64 encoded string
byte[] decodedKey = decoder.decode(key);
// rebuild key using SecretKeySpec
final SecretKeySpec originalKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, "RSA");
cipher.init(Cipher.DECRYPT_MODE, originalKey);
final String decryptedString = new String(cipher.doFinal(Base64.decodeBase64(new String(data))));
return decryptedString.getBytes();
} catch (Exception e) {
throw new CryptoServiceException("Cannot decrypt data using key '", e);
}
}
}
现在我得到了一个Junit,它在执行时抛出这个异常
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import junit.framework.Assert;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import **.CryptoServiceImpl;
public class TestCryptoService {
String privateKeyStore = "C:\\QA\\keys\\sis.jks";
String privateKeyStorePassword = "sistest";
String alias = "sis";
String aliasPassword = "sistest";
static ExtractKeys myep = new ExtractKeys();
CryptoService service = new CryptoServiceImpl();
String publicCertificate = "C:\\QA\\keys\\sis.cer";;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
}
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
@Test
public void testCryptoServiceForAESWithAsymmetricKeys() throws Exception {
String publicKey = myep.printPublicKey(publicCertificate);
byte[] encryptedValue = service.encrypt(new String("abcd").getBytes(), publicKey);
System.out.println(new String(encryptedValue));
String privateKey = myep.printPrivateKey(privateKeyStore, privateKeyStorePassword, alias, aliasPassword);
byte[] decryptedValue = service.decrypt(encryptedValue, privateKey);
System.out.println(new String(decryptedValue));
Assert.assertEquals("abcd", new String(decryptedValue));
}
}
*.CryptoServiceException: Cannot encrypt data using key '
at *.impl.CryptoServiceImpl.encrypt(CryptoServiceImpl.java:59)
at *.TestCryptoService.testCryptoServiceForAESWithAsymmetricKeys(TestCryptoService.java:101)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:95)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:56)
at java.lang.reflect.Method.invoke(Method.java:620)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.security.InvalidKeyException: Wrong algorithm type
at com.ibm.crypto.provider.RSAKeyFactory.engineTranslateKey(Unknown Source)
at com.ibm.crypto.provider.RSAKeyFactory.toRSAKey(Unknown Source)
at com.ibm.crypto.provider.RSACipher.engineGetKeySize(Unknown Source)
at javax.crypto.Cipher.b(Unknown Source)
at javax.crypto.Cipher.a(Unknown Source)
at javax.crypto.Cipher.a(Unknown Source)
at javax.crypto.Cipher.a(Unknown Source)
at javax.crypto.Cipher.init(Unknown Source)
at javax.crypto.Cipher.init(Unknown Source)
at *.impl.CryptoServiceImpl.encrypt(CryptoServiceImpl.java:55)
... 28 more
这是个例外
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import junit.framework.Assert;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import **.CryptoServiceImpl;
public class TestCryptoService {
String privateKeyStore = "C:\\QA\\keys\\sis.jks";
String privateKeyStorePassword = "sistest";
String alias = "sis";
String aliasPassword = "sistest";
static ExtractKeys myep = new ExtractKeys();
CryptoService service = new CryptoServiceImpl();
String publicCertificate = "C:\\QA\\keys\\sis.cer";;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
}
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
@Test
public void testCryptoServiceForAESWithAsymmetricKeys() throws Exception {
String publicKey = myep.printPublicKey(publicCertificate);
byte[] encryptedValue = service.encrypt(new String("abcd").getBytes(), publicKey);
System.out.println(new String(encryptedValue));
String privateKey = myep.printPrivateKey(privateKeyStore, privateKeyStorePassword, alias, aliasPassword);
byte[] decryptedValue = service.decrypt(encryptedValue, privateKey);
System.out.println(new String(decryptedValue));
Assert.assertEquals("abcd", new String(decryptedValue));
}
}
*.CryptoServiceException: Cannot encrypt data using key '
at *.impl.CryptoServiceImpl.encrypt(CryptoServiceImpl.java:59)
at *.TestCryptoService.testCryptoServiceForAESWithAsymmetricKeys(TestCryptoService.java:101)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:95)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:56)
at java.lang.reflect.Method.invoke(Method.java:620)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.security.InvalidKeyException: Wrong algorithm type
at com.ibm.crypto.provider.RSAKeyFactory.engineTranslateKey(Unknown Source)
at com.ibm.crypto.provider.RSAKeyFactory.toRSAKey(Unknown Source)
at com.ibm.crypto.provider.RSACipher.engineGetKeySize(Unknown Source)
at javax.crypto.Cipher.b(Unknown Source)
at javax.crypto.Cipher.a(Unknown Source)
at javax.crypto.Cipher.a(Unknown Source)
at javax.crypto.Cipher.a(Unknown Source)
at javax.crypto.Cipher.init(Unknown Source)
at javax.crypto.Cipher.init(Unknown Source)
at *.impl.CryptoServiceImpl.encrypt(CryptoServiceImpl.java:55)
... 28 more
证书虽然包含公钥,但不是公钥;更重要的是,像RSA这样的公钥加密(也称为非对称)方案的私钥或公钥或证书都不是对称密钥。Java
SecretKeySpec
仅适用于与对称算法(如AES)一起使用的对称密钥
您需要使用java.security.PrivateKey
和java.security.PublicKey
的子类型来表示RSA密钥。您可以使用RSA的KeyFactory
,或CertificateFactory
(就像您已经做的那样)
对于PKCS#8编码的私钥,即您编码并写出的私钥,请将其从PEM/base64解码为字节[]
,然后:
PKCS8EncodedKeySpec spec = new PKCSEncodedKeySpec (bytearray);
KeyFactory factory = KeyFactory.getInstance("RSA");
PrivateKey privkey = factory.generatePrivate (spec);
// use privkey in a Cipher.getInstance("RSA") to decrypt or sign
对于证书,请执行您已经执行的操作:
InputStream is = /* something that returns contents of cert file */;
// you *can* decode from PEM/base64 first, but you don't need to;
// CertificateFactory-X.509 handles both
CertificateFactory cf = CertificateFactory.getInstance ("X.509");
Certificate cert = cf.generateCertificate (is);
// use cert.getPublicKey() for RSA encrypt or verify
旁白:证书的sigalname不能说明证书中的密钥。完全有可能使用RSA签名的证书包含不能用于RSA的DSA或ECC密钥,反之,使用其他RSA变体(如SHA256withRSA)签名的证书包含非常好的RSA密钥或者完全不同的算法(如sha1 DSA或sha2 ECDSA)
还要注意:您正在显式导入
java.security.cert.Certificate
;那很好。JRE还有一个较旧且不推荐使用的java.security.Certificate
,您不应该使用它,但如果您只是说Certificate
,一些IDE(如我的)可能会混淆,并给出错误的IDE。在CryptoServiceImpl.java中标记第59行。人们很难找出异常的来源。@stacktrace中的erickson显示它在Cipher.init
中,调用自CryptoServiceImpl.encrypt
;只有一个这样的电话。