出于明显的安全原因,我需要用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));
}
一切正常,但在本例中,键对不是静态的,每次都会生成新值,但我需要使用相同的键,它们表示为字符串变量:
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类?
我做了如下工作:
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
。
在(大多数情况下)同意@JB的密码(通常)不应该被加密后,应该对密码进行“散列”——使用一种专门设计用于“拉伸”和salt的方法,比如scrypt,而不是像SHA-1这样的快速散列——同时还要注意,在原始代码中使用的RSA-512被破坏了,甚至在您的修改中显然使用的RSA-1024也被认为很弱:
您的Private ateKey值(从一开始)就显示为普通PKCS#1 DER编码的基数64,基本上仅由OpenSSL和使用OpenSSL(格式)的东西使用,如旧版本的OpenSSH。Java标准的“Sun”提供程序不处理这个问题,尽管我认为如果您想探索这个问题,BouncyCastle可能会处理。对于Sun,您需要将其从base 64转换为二进制DER;将其包装成PKCS#8格式(二进制格式只是添加一个头,也许是EOC拖车,因为PKCS#8用于RSA的算法特定部分是PKCS#1);并将其放入PKCS8EncodedKeySpec中,并通过RSA类型的KeyFactory
的GeneratePrivate运行
或者,添加标题/尾部以使其成为正确的PEM,使用OpenSSL将其转换为PKCS#8(未加密),并同时可选地转换为二进制,并通过generatePrivate
运行。
类似地,您的公钥似乎是X.509 SubjectPublicKeyInfo编码的base64,OpenSSL(但不是OpenSSH)使用该编码,标准Java在名称“X.509”下支持该编码。因此,只需将base64转换为二进制,放入X509EncodedKeySpec
,然后运行RSAKeyFactory的
generatePublic
。注意:如果加密将在远程或分布式进行,这是公钥加密的常见情况,则加密机必须确保使用正确的公钥;如果攻击者可以替换错误的公钥,他们可以解密并窃取至少一些您认为安全的数据。这就是为什么真正的PK系统不使用普通公钥,而是使用证书,比如SSL/TLS和s/MIME之类的X.509,或者PGP之类的信任网。
如果我了解您想要什么,要从静态变量中获取PublicKey和PrivateKey实例,您可以这样做,例如:
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) {
}
}
如何使用作为字符串提供的公共和私有RSA密钥进行加密和解密。因为我正在使用RSACryptoServiceProvider,它需要XML格式,所以是否有可能使用提供的字符串。谢谢。
我想得到一个文件内容的公钥,这是一个文件内容看起来像什么的例子(用生成): 如果我是对的,这不是公钥,但是可以从这个字符串中获取公钥。 这个答案回答了我的问题https://stackoverflow.com/a/19387517/2735398 但答案似乎不起作用。我有个例外: 当看到答案的评论时,我不是唯一有问题的人... 如何修复异常?或者有没有其他方法可以从字符串中获取公钥?
我可以直接从文件中读取公钥和私钥,因为文件流将其转换为PublicKey和PrivateKey对象。但如果以字符串形式加载,则失败。 工作代码 线程“main”java.security.spec.invalidkeyspection:java.security.invalidkeyexception:sun.security.rsa.rsakeyfactory.engineGeneratePub
在Android中,我使用下面的代码将String转换为RSA私钥 https://www.devglan.com/online-tools/rsa-encryption-decryption 但是,当我使用这个网站时,我的代码不起作用。 https://8gwifi.org/RSAFunctionality?keysize=1024 我在Android studio中的代码是: 与第二个链接错误
我一直在阅读一些RSA文献和堆栈溢出问题,但我没有得到明确的答案。 仅给定一个RSA私钥模和私钥指数,这是我所拥有的全部(也足够用于所有密码相关操作),我能得到相关的公钥模和公钥指数吗? 另外,我是否可以仅用这两个参数获得私钥的编码形式?我在java中尝试了以下方法(java不是实际的请求),但是支持它的OpenSSL引擎失败,错误为:04000090:RSA例程:openSSL_internal
我有一个公钥和一个私钥,还有一个字符串,我想要解密。 公钥的格式如下: 私钥的格式如下: 我要解密的字符串已经使用公钥加密,然后我需要使用私钥解密它。