投票系统中如何从RSA签名消息中获取原始消息内容?
问题分析与解决方案
你的核心问题在于混淆了RSA签名的作用:RSA签名是对原始消息的哈希值进行私钥加密生成的校验值,本身不包含原始消息内容,因此只传递签名的话,接收方根本无法获取到需要验证和解密的加密选票数据。
你需要把加密后的选票消息和对应的RSA签名一起传递给VotingSystem,才能完成签名验证和消息解密。以下是具体的修改方案:
1. 创建打包数据结构
首先定义一个类,用来同时携带加密后的选票和签名:
// 封装加密选票与签名的实体类 public class BallotPackage { private String encryptedBallot; private byte[] signature; public BallotPackage(String encryptedBallot, byte[] signature) { this.encryptedBallot = encryptedBallot; this.signature = signature; } // Getter方法 public String getEncryptedBallot() { return encryptedBallot; } public byte[] getSignature() { return signature; } }
2. 修改Voter类的vote方法
不再只传递签名,而是传递打包后的完整对象:
public void vote(String ballot, String gammaKey) throws Exception { String encryptedBallot = encrypt(ballot, gammaKey); byte[] signedMessage = signMessage(encryptedBallot); // 打包加密选票与签名后传递 votingSystem.addBallot(new BallotPackage(encryptedBallot, signedMessage)); }
3. 修改VotingSystem类的相关方法
更新addBallot参数类型,完善签名验证与消息解密逻辑:
public class VotingSystem { // 替换原有byte列表为BallotPackage列表 private ArrayList<BallotPackage> ballots = new ArrayList<>(); // 更新addBallot方法 public void addBallot(BallotPackage ballotPackage) { ballots.add(ballotPackage); } // 签名验证:使用打包对象中的加密选票数据进行校验 private boolean verifySign(BallotPackage ballotPackage, PublicKey publicKey) throws Exception { Signature publicSignature = Signature.getInstance("SHA256withRSA"); publicSignature.initVerify(publicKey); // 用加密后的选票消息更新签名验证器 publicSignature.update(ballotPackage.getEncryptedBallot().getBytes(StandardCharsets.UTF_8)); // 验证签名有效性 return publicSignature.verify(ballotPackage.getSignature()); } // 添加解密方法:还原原始选票内容 private String decrypt(String encryptedBallot, String gammaKey) { gammaKey = fitGammaToMessage(encryptedBallot.length(), gammaKey); StringBuilder decryptedMessage = new StringBuilder(); for (int i = 0; i < encryptedBallot.length(); i++) { // XOR解密逻辑与加密对称 char C = (char) (encryptedBallot.charAt(i) ^ gammaKey.charAt(i)); decryptedMessage.append(C); } return decryptedMessage.toString(); } // 补充fitGammaToMessage方法(与Voter类实现一致,或抽取为公共工具方法) private String fitGammaToMessage(int length, String gammaKey) { StringBuilder sb = new StringBuilder(gammaKey); while (sb.length() < length) { sb.append(gammaKey); } return sb.substring(0, length); } // 示例:批量处理选票的方法 public void processBallots(PublicKey voterPublicKey, String gammaKey) throws Exception { for (BallotPackage pkg : ballots) { // 先验证签名 boolean isSignValid = verifySign(pkg, voterPublicKey); if (!isSignValid) { System.out.println("签名无效,丢弃选票"); continue; } // 签名有效则解密选票 String originalBallot = decrypt(pkg.getEncryptedBallot(), gammaKey); System.out.println("验证通过,原始选票内容:" + originalBallot); // 后续业务逻辑处理... } } }
额外优化建议
- 避免不可打印字符问题:你的XOR加密可能生成不可打印ASCII字符,直接用String存储易导致数据损坏,建议将加密后的字节数组转成Base64字符串,解密时再转回字节数组。
- 密钥安全管理:伽马密钥(gammaKey)需安全传递给
VotingSystem,禁止硬编码;RSA公钥的传递也要确保可信渠道。 - 完善异常处理:代码中需补充异常捕获逻辑,避免RuntimeException扩散。
内容的提问来源于stack exchange,提问作者PrettyCoder
相关产品推荐
相关产品推荐

