使用Java API执行RSA签名及基于BigInteger的验证技术问询
Hey there! I see you're looking to implement RSA signing and verification using Java—both with the standard API and your custom BigInteger-based RSA class. Let's walk through both approaches step by step.
1. Standard Java API Implementation
Java's java.security package has all the tools you need for RSA signing without rolling your own BigInteger logic. Here's how to do it:
Generate RSA Key Pair
import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; public class StandardRSAExample { public static KeyPair generateRSAKeyPair(int keySize) throws NoSuchAlgorithmException { KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); SecureRandom secureRandom = new SecureRandom(); keyGen.initialize(keySize, secureRandom); return keyGen.generateKeyPair(); } }
Sign Data with Private Key
Signing requires hashing the data first (we'll use SHA-256 here) and then encrypting the hash with the private key:
import java.security.PrivateKey; import java.security.Signature; import java.util.Base64; public static String signData(String data, PrivateKey privateKey) throws Exception { Signature signature = Signature.getInstance("SHA256withRSA"); signature.initSign(privateKey); signature.update(data.getBytes()); byte[] signedBytes = signature.sign(); return Base64.getEncoder().encodeToString(signedBytes); }
Verify Signature with Public Key
To verify, we hash the original data again, decrypt the signature with the public key, and compare the two hashes:
import java.security.PublicKey; public static boolean verifySignature(String data, String signedData, PublicKey publicKey) throws Exception { Signature signature = Signature.getInstance("SHA256withRSA"); signature.initVerify(publicKey); signature.update(data.getBytes()); byte[] decodedSignature = Base64.getDecoder().decode(signedData); return signature.verify(decodedSignature); }
2. Enhancing Your Custom BigInteger-Based RSA Class
Your existing code starts the key generation process, but let's complete it and add signing/verification methods. First, let's define a RSAKeyPair class to hold the public (n, e) and private (n, d) keys:
class RSAKeyPair { private BigInteger n; // Modulus private BigInteger e; // Public exponent private BigInteger d; // Private exponent public RSAKeyPair(BigInteger n, BigInteger e, BigInteger d) { this.n = n; this.e = e; this.d = d; } // Getters public BigInteger getN() { return n; } public BigInteger getE() { return e; } public BigInteger getD() { return d; } }
Now complete the RSA class with full key generation, signing, and verification:
import java.security.SecureRandom; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; class RSA { public static RSAKeyPair generateKeyPair(int size) { SecureRandom rnd = new SecureRandom(); BigInteger p = new BigInteger(size / 2, 100, rnd); BigInteger q = new BigInteger(size / 2, 100, rnd); BigInteger n = p.multiply(q); BigInteger phi = p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE)); BigInteger e; // Find e: must be coprime with phi, 1 < e < phi do { e = new BigInteger(phi.bitLength(), rnd); } while (e.compareTo(BigInteger.ONE) <= 0 || e.compareTo(phi) >= 0 || !e.gcd(phi).equals(BigInteger.ONE)); // Calculate private exponent d: modular inverse of e mod phi BigInteger d = e.modInverse(phi); return new RSAKeyPair(n, e, d); } // Sign data: hash first, then apply private key operation (m^d mod n) public static BigInteger sign(String data, RSAKeyPair keyPair) throws NoSuchAlgorithmException { // Hash the data with SHA-256 MessageDigest md = MessageDigest.getInstance("SHA-256"); byte[] hash = md.digest(data.getBytes()); BigInteger hashBigInt = new BigInteger(1, hash); // Positive big integer from hash bytes // Sign: hash^d mod n return hashBigInt.modPow(keyPair.getD(), keyPair.getN()); } // Verify signature: decrypt signature with public key (s^e mod n) and compare to hash of original data public static boolean verify(String data, BigInteger signature, RSAKeyPair keyPair) throws NoSuchAlgorithmException { MessageDigest md = MessageDigest.getInstance("SHA-256"); byte[] originalHash = md.digest(data.getBytes()); BigInteger originalHashBigInt = new BigInteger(1, originalHash); // Decrypt signature: s^e mod n BigInteger decryptedSignature = signature.modPow(keyPair.getE(), keyPair.getN()); // Compare the decrypted signature with the original hash return decryptedSignature.equals(originalHashBigInt); } }
Quick Key Notes
- Always hash data before signing: RSA is designed to sign small values (like hashes), not large raw data. Using SHA-256 ensures we're working with a fixed-size, secure input.
- Key size: For modern security, use at least 2048-bit keys (3072-bit is better for long-term protection).
- SecureRandom: Never skip using
SecureRandomfor key generation—it ensures your keys are unpredictable and hard to crack.
内容的提问来源于stack exchange,提问作者user9676331

