在Java下进行RSA加密(私钥加密,公钥解密)

41 篇文章 1 订阅
38 篇文章 0 订阅

加密过长的会报错:

Data must not be longer than 245 bytes

原因是应为不同长度的密钥对应可以加密不同最大长度的原文,2048就对应245

解决办法是:

方案一: 分段

方案二: RSA加密是有长度限制的.单纯用RSA加密较长数据时得使用分段加密,效率低下.用RSA+AES是比较主流的做法:AES加密数据产生密文,RSA加密AES密钥产生加密后的AES密钥,然后将密文和加密后的AES密钥一起传输:https://blog.csdn.net/huang007guo/article/details/104639490

package com.wjj.application.paysdk.crypt.tools;

import org.bouncycastle.crypto.InvalidCipherTextException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * RSA 加密工具 参考:https://www.devglan.com/java8/rsa-encryption-decryption-java
 * 加密过长的会报错:
 Data must not be longer than 245 bytes
 原因是应为不同长度的密钥对应可以加密不同最大长度的原文,2048就对应245
 解决办法是:
 1.分段
 2.RSA加密是有长度限制的.单纯用RSA加密较长数据时得使用分段加密,效率低下.用RSA+AES是比较主流的做法:AES加密数据产生密文,RSA加密AES密钥产生加密后的AES密钥,然后将密文和加密后的AES密钥一起传输
 * @author hank
 * @since 2020/2/28 0028 下午 15:42
 */
public class RsaCryptTools {
    private static final String CHARSET = "utf-8";
    private static final Base64.Decoder decoder64 = Base64.getDecoder();
    private static final Base64.Encoder encoder64 = Base64.getEncoder();

    /**
     * 生成公私钥
     * @param keySize
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static SecretKey generateSecretKey(int keySize) throws NoSuchAlgorithmException {
        //生成密钥对
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        keyGen.initialize(keySize, new SecureRandom());
        KeyPair pair = keyGen.generateKeyPair();
        PrivateKey privateKey = pair.getPrivate();
        PublicKey publicKey = pair.getPublic();
        //这里可以将密钥对保存到本地
        return new SecretKey(encoder64.encodeToString(publicKey.getEncoded()), encoder64.encodeToString(privateKey.getEncoded()));
    }
    /**
     * 私钥加密
     * @param data
     * @param privateInfoStr
     * @return
     * @throws IOException
     * @throws InvalidCipherTextException
     */
    public static String encryptData(String data, String privateInfoStr) throws IOException, InvalidKeySpecException, NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException {

        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, getPrivateKey(privateInfoStr));
        return encoder64.encodeToString(cipher.doFinal(data.getBytes(CHARSET)));
    }

    /**
     * 公钥解密
     * @param data
     * @param publicInfoStr
     * @return
     */
    public static String decryptData(String data, String publicInfoStr) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException {
        byte[] encryptDataBytes=decoder64.decode(data.getBytes(CHARSET));
        //解密
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, getPublicKey(publicInfoStr));
        return new String(cipher.doFinal(encryptDataBytes), CHARSET);
    }
    private static PublicKey getPublicKey(String base64PublicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(base64PublicKey.getBytes()));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePublic(keySpec);
    }
    private static PrivateKey getPrivateKey(String base64PrivateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
        PrivateKey privateKey = null;
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(base64PrivateKey.getBytes()));
        KeyFactory keyFactory = null;
        keyFactory = KeyFactory.getInstance("RSA");
        privateKey = keyFactory.generatePrivate(keySpec);
        return privateKey;
    }

    /**
     * 密钥实体
     * @author hank
     * @since 2020/2/28 0028 下午 16:27
     */
    public static class SecretKey {
        /**
         * 公钥
         */
        private String publicKey;
        /**
         * 私钥
         */
        private String privateKey;

        public SecretKey(String publicKey, String privateKey) {
            this.publicKey = publicKey;
            this.privateKey = privateKey;
        }

        public String getPublicKey() {
            return publicKey;
        }

        public void setPublicKey(String publicKey) {
            this.publicKey = publicKey;
        }

        public String getPrivateKey() {
            return privateKey;
        }

        public void setPrivateKey(String privateKey) {
            this.privateKey = privateKey;
        }

        @Override
        public String toString() {
            return "SecretKey{" +
                    "publicKey='" + publicKey + '\'' +
                    ", privateKey='" + privateKey + '\'' +
                    '}';
        }
    }

    private static void writeToFile(String path, byte[] key) throws IOException {
        File f = new File(path);
        f.getParentFile().mkdirs();

        try(FileOutputStream fos = new FileOutputStream(f)) {
            fos.write(key);
            fos.flush();
        }
    }

    public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, IOException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException, InvalidKeySpecException {
        SecretKey secretKey = generateSecretKey(2048);
        System.out.println(secretKey);
        String enStr = encryptData("你好测试测试", secretKey.getPrivateKey());
        System.out.println(enStr);
        String deStr = decryptData(enStr, secretKey.getPublicKey());
        System.out.println(deStr);
        enStr = encryptData("你好测试测试hello", secretKey.getPrivateKey());
        System.out.println(enStr);
        deStr = decryptData(enStr, secretKey.getPublicKey());
        System.out.println(deStr);
    }

}

  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个简单的示例,展示了如何使用 OpenSSL 库进行 RSA 加密解密。 首先,我们需要生成一对 RSA 密钥。这可以使用以下命令完成: ``` openssl genrsa -out private_key.pem 2048 openssl rsa -in private_key.pem -pubout -out public_key.pem ``` 其中,`private_key.pem` 是生成的私钥文件,`public_key.pem` 是生成的公钥文件。 接下来,我们可以使用以下代码来进行 RSA 加密解密: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <openssl/rsa.h> #include <openssl/pem.h> int main() { RSA *rsa = NULL; FILE *fp = NULL; int rsa_len = 0; unsigned char *encrypted = NULL; unsigned char *decrypted = NULL; // 读取公钥文件 fp = fopen("public_key.pem", "r"); if (fp == NULL) { printf("Failed to open public key file\n"); return -1; } rsa = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL); fclose(fp); if (rsa == NULL) { printf("Failed to read public key\n"); return -1; } // 计算 RSA 密钥长度 rsa_len = RSA_size(rsa); // 分配加密解密缓冲区 encrypted = (unsigned char*)malloc(rsa_len * sizeof(unsigned char)); decrypted = (unsigned char*)malloc(rsa_len * sizeof(unsigned char)); // 要加密的明文 const char *plain_text = "Hello, RSA!"; int plain_text_len = strlen(plain_text); // 加密明文 int encrypted_len = RSA_public_encrypt(plain_text_len, (unsigned char*)plain_text, encrypted, rsa, RSA_PKCS1_PADDING); if (encrypted_len == -1) { printf("Failed to encrypt\n"); return -1; } // 输出加密后的结果 printf("Encrypted: "); for (int i = 0; i < encrypted_len; i++) { printf("%02x", encrypted[i]); } printf("\n"); // 读取私钥文件 fp = fopen("private_key.pem", "r"); if (fp == NULL) { printf("Failed to open private key file\n"); return -1; } rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); fclose(fp); if (rsa == NULL) { printf("Failed to read private key\n"); return -1; } // 解密密文 int decrypted_len = RSA_private_decrypt(encrypted_len, encrypted, decrypted, rsa, RSA_PKCS1_PADDING); if (decrypted_len == -1) { printf("Failed to decrypt\n"); return -1; } // 输出解密后的结果 printf("Decrypted: %s\n", decrypted); free(encrypted); free(decrypted); return 0; } ``` 在上述示例中,我们首先读取公钥文件,然后计算 RSA 密钥长度,并分配加密解密缓冲区。接下来,我们使用 `RSA_public_encrypt` 函数对明文进行加密,并使用 `RSA_private_decrypt` 函数对密文进行解密。在解密后,我们可以输出解密后的结果。 需要注意的是,在实际使用中,我们应该使用更安全的填充方式,如 RSA OAEP 填充。此外,为了确保安全,我们应该使用随机数生成器来生成 RSA 密钥。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值