java - 没有填充的 Java RSA
问题描述
我正在尝试实现没有填充的 RSA 加密。如果我多次加密相同的东西,我需要它来获得相同的密文。问题是,即使我似乎设法做到了,密文也没有解密。如果我将“RSA/ECB/NoPadding”替换为“RSA”,则下面的代码有效。
import javax.crypto.Cipher;
import java.io.InputStream;
import java.security.*;
import java.util.Base64;
import static java.nio.charset.StandardCharsets.UTF_8;
public class RsaExample {
//https://gist.github.com/nielsutrecht/855f3bef0cf559d8d23e94e2aecd4ede
public static KeyPair generateKeyPair() throws Exception {
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(2048, new SecureRandom());
KeyPair pair = generator.generateKeyPair();
return pair;
}
public static KeyPair getKeyPairFromKeyStore() throws Exception {
//Generated with:
// keytool -genkeypair -alias mykey -storepass s3cr3t -keypass s3cr3t -keyalg RSA -keystore keystore.jks
InputStream ins = RsaExample.class.getResourceAsStream("/keystore.jks");
KeyStore keyStore = KeyStore.getInstance("JCEKS");
keyStore.load(ins, "s3cr3t".toCharArray()); //Keystore password
KeyStore.PasswordProtection keyPassword = //Key password
new KeyStore.PasswordProtection("s3cr3t".toCharArray());
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry("mykey", keyPassword);
java.security.cert.Certificate cert = keyStore.getCertificate("mykey");
PublicKey publicKey = cert.getPublicKey();
PrivateKey privateKey = privateKeyEntry.getPrivateKey();
return new KeyPair(publicKey, privateKey);
}
public static String encrypt(String plainText, PublicKey publicKey) throws Exception {
Cipher encryptCipher = Cipher.getInstance("RSA/ECB/NoPadding");
encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] cipherText = encryptCipher.doFinal(plainText.getBytes(UTF_8));
return Base64.getEncoder().encodeToString(cipherText);
}
public static String decrypt(String cipherText, PrivateKey privateKey) throws Exception {
byte[] bytes = Base64.getDecoder().decode(cipherText);
Cipher decriptCipher = Cipher.getInstance("RSA/ECB/NoPadding");
decriptCipher.init(Cipher.DECRYPT_MODE, privateKey);
return new String(decriptCipher.doFinal(bytes), UTF_8);
}
public static String sign(String plainText, PrivateKey privateKey) throws Exception {
Signature privateSignature = Signature.getInstance("SHA256withRSA");
privateSignature.initSign(privateKey);
privateSignature.update(plainText.getBytes(UTF_8));
byte[] signature = privateSignature.sign();
return Base64.getEncoder().encodeToString(signature);
}
public static boolean verify(String plainText, String signature, PublicKey publicKey) throws Exception {
Signature publicSignature = Signature.getInstance("SHA256withRSA");
publicSignature.initVerify(publicKey);
publicSignature.update(plainText.getBytes(UTF_8));
byte[] signatureBytes = Base64.getDecoder().decode(signature);
return publicSignature.verify(signatureBytes);
}
public static void main(String... argv) throws Exception {
//First generate a public/private key pair
KeyPair pair = generateKeyPair();
//KeyPair pair = getKeyPairFromKeyStore();
//Our secret message
String message = "the answer to life the universe and everything";
//Encrypt the message
String cipherText = encrypt(message, pair.getPublic());
System.out.println("Cipher 1="+ cipherText);
String cipherText2 = encrypt(message, pair.getPublic());
System.out.println("Cipher 2="+ cipherText2);
//Now decrypt it
String decipheredMessage = decrypt(cipherText, pair.getPrivate());
//System.out.println("Private "+pair.getPrivate().toString());
System.out.println("Deciphered "+ decipheredMessage);
//Let's sign our message
String signature = sign("foobar", pair.getPrivate());
System.out.println("Signature "+signature);
//Let's check the signature
boolean isCorrect = verify("foobar", signature, pair.getPublic());
System.out.println("Signature correct: " + isCorrect);
}
}
任何帮助,将不胜感激。
解决方案
推荐阅读
- c++ - 使用 reinterpret_cast 访问私有数据
- asp.net - ASP.Net Azure Web 应用程序身份验证重定向到域而不是 localhost
- spring-boot - Spring Boot 2.3.2.RELEASE - Micrometer - KafkaMetrics - 无法绑定仪表日志
- spring - Spring URL 授权失败,用户在 WebExpressionV 中不是匿名的
- gpu - 使用 GPU 的统一内存(UM 或 SVA)模式的真实场景是什么?
- google-chrome - WebSerial API 设备无法在 Ubuntu 上打开端口
- c# - Selenium (c#) - html 元素中没有唯一标识符 - javascript?
- parsing - 如何定义像 Scala/Rust 一样混合语句和表达式语法的简单编程语言语法?
- javascript - Chrome扩展程序:切换标签时如何重新加载扩展程序
- c# - 将收集到的积分限制为每级三个(就像愤怒的小鸟中的星星)