AES加密 + RSA签名

public class Main {
    public static void main(String[] args) throws Exception {
        // 生成RSA密钥对
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        keyGen.initialize(1024);
        KeyPair keyPair = keyGen.generateKeyPair();
        PublicKey publicKey = keyPair.getPublic();
        PrivateKey privateKey = keyPair.getPrivate();

        // 将公钥和私钥转换为Base64编码的字符串
        String rsaPublicKeyStr = Base64.getEncoder().encodeToString(publicKey.getEncoded());
        String rsaPrivateKeyStr = Base64.getEncoder().encodeToString(privateKey.getEncoded());
        // 对称加密算法
        String algorithm = "AES";

        // AES密钥(长度通常为128、192或256位)
        KeyGenerator aesKeyFactor = KeyGenerator.getInstance(algorithm);
        aesKeyFactor.init(128); // 128-bit AES key
        byte[] aesKey = aesKeyFactor.generateKey().getEncoded();
//        String key = "1234567812345678"; // 16字节*8 = 128位

        // 敏感信息
        String content = "{\"dog_name\":\"小.王\",\"dogGender\":\"male\"}";
        String timestamp = String.valueOf(System.currentTimeMillis());
        // 拼接时间戳
        content = timestamp + "|" + content;

        System.out.println("\n-----------发送方-----------\n");

        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        SecretKeySpec keySpec = new SecretKeySpec(aesKey, algorithm);
        // 随机初始化向量iv,以实现相同content加密后的密文是不同的
        byte[] iv = new byte[12];
        SecureRandom random = new SecureRandom();
        random.nextBytes(iv);
        String ivStr = Base64.getEncoder().encodeToString(iv);
        GCMParameterSpec gcmSpec = new GCMParameterSpec(128, iv);
        // 加密模式
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, gcmSpec);
        byte[] encryptBytes = cipher.doFinal(content.getBytes());
        String encryptText = Base64.getEncoder().encodeToString(encryptBytes);


        // RSA私钥签名
        PrivateKey rsaPrivateKey = recoverPrivateKey(rsaPrivateKeyStr);
        Signature signer = Signature.getInstance("SHA256withRSA");
        signer.initSign(rsaPrivateKey);
        // 获取SHA-256 MessageDigest实例
        MessageDigest digest = MessageDigest.getInstance("SHA-256");

        // 对密文进行哈希处理
        byte[] hashBytes = digest.digest(encryptText.getBytes());
        signer.update(hashBytes); // 对密文的哈希值进行签名(而非对密文本身签名),以此避免得到过长的签名结果
        byte[] signatureBytes = signer.sign();
        String signature = Base64.getEncoder().encodeToString(signatureBytes);

        // 输出结果
        System.out.println("Encrypted Text: " + encryptText);
        System.out.println("Signature: " + signature);
        System.out.println("ivStr: " + ivStr);

        System.out.println("\n-----------接收方-----------\n");

        // 验签
        PublicKey rsaPublicKey = recoverPublicKey(rsaPublicKeyStr);
        Signature verifier = Signature.getInstance("SHA256withRSA");
        verifier.initVerify(rsaPublicKey);
        verifier.update(hashBytes);
        boolean isCorrect = verifier.verify(Base64.getDecoder().decode(signature));
        if (isCorrect) {
            System.out.println("验签成功");
        } else {
            System.out.println("验签失败");
        }

        // 解密
        Cipher recieverCipher = Cipher.getInstance("AES/GCM/NoPadding");
        SecretKeySpec receiverSk = new SecretKeySpec(aesKey, algorithm);
        byte[] receiverIv = Base64.getDecoder().decode(ivStr);
        GCMParameterSpec gcm = new GCMParameterSpec(128, receiverIv);
        // 解密模式
        recieverCipher.init(Cipher.DECRYPT_MODE, receiverSk, gcm);
        // 先将加密后的字符串解码回字节数据
        byte[] decodedBytes = Base64.getDecoder().decode(encryptText);
        byte[] plainBytes = recieverCipher.doFinal(decodedBytes);
        String plainText = new String(plainBytes).split("\\|")[1]; // 原文
        System.out.println(plainText);
    }

    private static PublicKey recoverPublicKey(String key) throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(key);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePublic(keySpec);
    }

    private static PrivateKey recoverPrivateKey(String key) throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(key);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(keySpec);
    }
}

 

AES加密+RSA签名的方案结合了AES的高加密速度和RSA的签名验证能力,适用于需要同时保证数据传输的机密性、完整性和来源可靠性的场景。例如,在网络通信中,可以使用AES加密数据内容,使用RSA签名来验证数据的完整性和来源。

结合了AES和RSA的优点,既保证了数据传输的速度和效率,又确保了数据的安全性和可靠性。

posted @ 2024-09-14 17:13  Ashe|||^_^  阅读(11)  评论(0编辑  收藏  举报