出于明显的安全原因,我需要使用RSA私钥和公钥加密和解密用户的PIN码,我找到了工作解决方案,如下所示:
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(512);
KeyPair rsaKeyPair = kpg.genKeyPair();
byte[] txt = "This is a secret message.".getBytes();
System.out.println("Original clear message: " + new String(txt));
// encrypt
Cipher cipher;
try {
cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, rsaKeyPair.getPublic());
txt = cipher.doFinal(txt);
} catch (Throwable e) {
e.printStackTrace();
return;
}
System.out.println("Encrypted message: " + new String(txt));
// decrypt
try {
cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, rsaKeyPair.getPrivate());
txt = cipher.doFinal(txt);
} catch (Throwable e) {
e.printStackTrace();
return;
}
System.out.println("Decrypted message: " + new String(txt));
}
一切正常,但在这个示例中,密钥对不是静态的,每次都会生成新值,但我需要使用相同的密钥,它们表示为String变量:
public static final String PrivateKey = "MIICXAIBAAKBgQDx0PSJr6zEP9914k1eM+sS8/eW+FenhBQI/jf6ARe8kZHFig9Y"
+ bla bla bla
+ "wdK3jBzObK319yNFr/2LukNZ9Bgv7fS78roBvxbe2gI=";
public static final String PublicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDx0PSJr6zEP9914k1eM+sS8/eW"
+ bla bla bla
+ "jYo5w2Nhxe2cukCQMQIDAQAB";
有没有办法将这些变量强制转换为PublicKey和PrivateKey Class?
答案 0 :(得分:1)
如果我理解你想要什么,从你的静态变量中获取公钥和私钥实例,你可以这样做,例如,这样:
private static final String privateKeyString = "...";
private static PrivateKey privateKey;
private static final String publicKeyString = "...";
private static PublicKey publicKey;
static {
KeyFactory kf;
try {
kf = KeyFactory.getInstance("RSA");
byte[] encodedPv = Base64.decodeBase64(privateKeyString);
PKCS8EncodedKeySpec keySpecPv = new PKCS8EncodedKeySpec(encodedPv);
privateKey = kf.generatePrivate(keySpecPv);
byte[] encodedPb = Base64.decodeBase64(publicKeyString);
X509EncodedKeySpec keySpecPb = new X509EncodedKeySpec(encodedPb);
publicKey = kf.generatePublic(keySpecPb);
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
}
}
答案 1 :(得分:0)
在(大多数情况下)同意@JB之后,密码(通常)不应该被加密,它们应该是"哈希" - 使用专门为"伸展" 和盐如scrypt,而不是像SHA-1这样的快速哈希 - 并且还注意到原始代码中使用的RSA-512已损坏,甚至RSA-1024在您的修改中显然也是如此被认为是弱者:
您的PrivateKey值(从一开始)显示为普通PKCS#1 DER编码的base64,它基本上仅由OpenSSL和使用OpenSSL(格式)的东西使用,如旧版本的OpenSSH。 Java标准" Sun"提供商不会处理这个,虽然我认为BouncyCastle可能是你想探索它。对于Sun,您需要将其从base64转换为二进制DER;将其包装成PKCS#8格式(二进制文件只是添加标题和EOC预告片,因为RSA 的PKCS#8的算法特定部分是 PKCS#1 );并将其放入PKCS8EncodedKeySpec
并运行generatePrivate
类型的RSA KeyFactory
。见
或者添加标题/预告片以使其成为正确的PEM,使用OpenSSL将其转换为PKCS#8(未加密),并同时选择二进制,并通过generatePrivate
运行。
你的PublicKey同样似乎是X.509 SubjectPublicKeyInfo编码的base64,OpenSSL(但不是OpenSSH)使用它,标准Java 支持名称" X.509&#34 ;。因此,只需将base64转换为二进制文件,放入X509EncodedKeySpec
,然后运行RSA generatePublic
的{{1}}。请注意,如果您的加密是远程或分布式的,这是publickey-encryption的常用方案,加密器必须确保使用正确的公钥;如果攻击者可以替换错误的公钥,他们可以解密并窃取至少一些你所谓的安全数据。这就是为什么真正的PK系统不使用普通公钥,他们使用证书,如X.509,如SSL / TLS和S / MIME,或者像PGP一样的信任网。
答案 2 :(得分:0)
我正在执行以下操作:
public Key loadPrivateKey(String stored) throws GeneralSecurityException {
PKCS8EncodedKeySpec keySpec =
new PKCS8EncodedKeySpec(
Base64.getDecoder().decode(stored.getBytes(StandardCharsets.UTF_8)));
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(keySpec);
}
public Key loadPublicKey(String stored) throws GeneralSecurityException {
byte[] data = Base64.getDecoder().decode(stored.getBytes(StandardCharsets.UTF_8));
X509EncodedKeySpec spec = new X509EncodedKeySpec(data);
KeyFactory fact = KeyFactory.getInstance("RSA");
return fact.generatePublic(spec);
}
您还必须从包含您的密钥的字符串中删除-----BEGIN PRIVATE KEY-----
,-----END PRIVATE KEY-----
和所有\n
。