美文网首页Java web
Java 实现 RSA 加密

Java 实现 RSA 加密

作者: 又语 | 来源:发表于2020-04-12 10:59 被阅读0次

本文介绍 RSA 加密的原理、示例、安全性分析及 Java 语言实现。


目录

  • RSA 简介
    • 原理
    • 示例
    • 安全性
    • 常见用途
  • 代码实现

RSA 简介

RSA 是一种非对称加密算法,于1977年由 MIT 的 Ron Rivest,Adi Shamir 和 Leonard Adleman 三人一起提出。

原理及示例
  1. 选择 2 个质数 pq
  2. 计算 n = p * q
  3. 根据欧拉函数 φ(n) = (p - 1) * (q - 1) 计算出 φ(n)
  4. 确定公钥(整数)e,要求:1 < e < φ(n)eφ(n) 互质
  5. 确定私钥(整数)d,要求:(e * d) / φ(n) 的余数为 1
  6. 加密:原文 m,计算 me 次幂除以 n,求余数 cc 就是加密后所得的密文
  7. 解密:密文 c,计算 cd 次幂除以 n,求余数得到原文 m
示例

来自 wikipedia

  1. p = 61q = 53
  2. n = 61 * 53 = 3233
  3. φ(n) = (61 - 1) * (53 - 1) = 60 * 52 = 3120
  4. e = 17
  5. d = 2753
  6. 公钥 (3233,17),私钥 (3233,2753)
  7. 原文 18,公钥加密密文 2100,私钥解密得到原文 18
  8. 原文 81,私钥加密密文 2083,公钥解密得到原文 81
安全性
  1. 加解需要 n 和公钥 e 生成密文 c
  2. 解密需要 n 、密钥 d 和密文 c
  3. 公开场合窃听者只能获取 n e c,但是获取不到密钥 d,需要通过 e 计算出 d
  4. 如果想通过 e 计算出 d 则必须知道 φ(n)
  5. 想知道 φ(n) 必须求出 pq
  6. 因为 n = p * qn 已知,所以必须进行【质因数分解】,数学证明大数质因数分解十分困难,这也是 RSA 算法安全性的根本保证。

美国国家标准与技术局和 ANSI X9 已经设定了最小密钥长度的要求,RSA 是 2048 位,这样在 2030 年以前是安全的。

常见用途
  • 公钥加密、私钥解密:加密数据及信息
  • 私钥加密、公钥解密:数字签名

代码实现

package tutorial.java.util;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.security.*;
import java.util.Base64;

public class RsaUtils {

    /**
     * 算法名称
     */
    private static final String ALGORITHM_RSA = "RSA";

    /**
     * 签名算法
     */
    public static final String SIGNATURE_ALGORITHM = "SHA512withRSA";

    /**
     * 生成密钥对
     *
     * @param keySize 密钥长度
     * @return 密钥对
     */
    public static KeyPair keyPair(int keySize) throws NoSuchAlgorithmException {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM_RSA);
        keyPairGenerator.initialize(keySize);
        return keyPairGenerator.generateKeyPair();
    }

    /**
     * RSA 私钥加密
     *
     * @param privateKey 私钥
     * @param content    待加密内容
     * @return 加密后密文字节数组
     */
    public static byte[] encryptByPrivateKey(PrivateKey privateKey, byte[] content) {
        try {
            Cipher cipher = Cipher.getInstance(ALGORITHM_RSA);
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            return cipher.doFinal(content);
        } catch (NoSuchAlgorithmException e) {
            throw new UnsupportedOperationException("No Such Algorithm");
        } catch (NoSuchPaddingException e) {
            throw new UnsupportedOperationException("No Such Padding");
        } catch (InvalidKeyException e) {
            throw new UnsupportedOperationException("Invalid Key");
        } catch (BadPaddingException e) {
            throw new UnsupportedOperationException("Bad Padding");
        } catch (IllegalBlockSizeException e) {
            throw new UnsupportedOperationException("Illegal Block Size");
        }
    }

    /**
     * RSA 公钥加密
     *
     * @param publicKey 公钥
     * @param content   待加密内容
     * @return 加密后密文字节数组
     */
    public static byte[] encryptByPublicKey(PublicKey publicKey, byte[] content) {
        try {
            Cipher cipher = Cipher.getInstance(ALGORITHM_RSA);
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            return cipher.doFinal(content);
        } catch (NoSuchAlgorithmException e) {
            throw new UnsupportedOperationException("No Such Algorithm");
        } catch (NoSuchPaddingException e) {
            throw new UnsupportedOperationException("No Such Padding");
        } catch (InvalidKeyException e) {
            throw new UnsupportedOperationException("Invalid Key");
        } catch (BadPaddingException e) {
            throw new UnsupportedOperationException("Bad Padding");
        } catch (IllegalBlockSizeException e) {
            throw new UnsupportedOperationException("Illegal Block Size");
        }
    }

    /**
     * RSA 私钥解密
     *
     * @param privateKey 私钥
     * @param content    密文
     * @return 解密后原文字节数组
     */
    public static byte[] decryptByPrivateKey(PrivateKey privateKey, byte[] content) {
        try {
            Cipher cipher = Cipher.getInstance(ALGORITHM_RSA);
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            return cipher.doFinal(content);
        } catch (NoSuchAlgorithmException e) {
            throw new UnsupportedOperationException("No Such Algorithm");
        } catch (NoSuchPaddingException e) {
            throw new UnsupportedOperationException("No Such Padding");
        } catch (InvalidKeyException e) {
            throw new UnsupportedOperationException("Invalid Key");
        } catch (BadPaddingException e) {
            throw new UnsupportedOperationException("Bad Padding");
        } catch (IllegalBlockSizeException e) {
            throw new UnsupportedOperationException("Illegal Block Size");
        }
    }

    /**
     * RSA 公钥解密
     *
     * @param publicKey 公钥
     * @param content   密文
     * @return 解密后原文字节数组
     */
    public static byte[] decryptByPublicKey(PublicKey publicKey, byte[] content) {
        try {
            Cipher cipher = Cipher.getInstance(ALGORITHM_RSA);
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            return cipher.doFinal(content);
        } catch (NoSuchAlgorithmException e) {
            throw new UnsupportedOperationException("No Such Algorithm");
        } catch (NoSuchPaddingException e) {
            throw new UnsupportedOperationException("No Such Padding");
        } catch (InvalidKeyException e) {
            throw new UnsupportedOperationException("Invalid Key");
        } catch (BadPaddingException e) {
            throw new UnsupportedOperationException("Bad Padding");
        } catch (IllegalBlockSizeException e) {
            throw new UnsupportedOperationException("Illegal Block Size");
        }
    }

    /**
     * 用私钥生成数字签名
     *
     * @param content    签名内容
     * @param privateKey 私钥
     * @return 数字签名
     */
    public static String sign(byte[] content, PrivateKey privateKey) {
        try {
            Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
            signature.initSign(privateKey);
            signature.update(content);
            return Base64.getEncoder().encodeToString(signature.sign());
        } catch (NoSuchAlgorithmException e) {
            throw new UnsupportedOperationException("No Such Algorithm");
        } catch (SignatureException e) {
            throw new UnsupportedOperationException("Signature Exception");
        } catch (InvalidKeyException e) {
            throw new UnsupportedOperationException("Invalid Key");
        }
    }

    /**
     * 用公钥验证数字签名
     *
     * @param content   签名内容
     * @param publicKey 公钥
     * @param sign      签名
     * @return 验证结果
     */
    public static boolean verify(byte[] content, PublicKey publicKey, String sign) {
        try {
            Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
            signature.initVerify(publicKey);
            signature.update(content);
            return signature.verify(Base64.getDecoder().decode(sign));
        } catch (NoSuchAlgorithmException e) {
            throw new UnsupportedOperationException("No Such Algorithm");
        } catch (SignatureException e) {
            throw new UnsupportedOperationException("Signature Exception");
        } catch (InvalidKeyException e) {
            throw new UnsupportedOperationException("Invalid Key");
        }
    }
}

单元测试:

package tutorial.java.util;

import org.junit.Assert;
import org.junit.Test;

import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;

public class RsaUtilsTest {

    @Test
    public void test() throws NoSuchAlgorithmException {
        String content = "RSA encrypt/decrypt demo";
        KeyPair keyPair = RsaUtils.keyPair(2048);
        // 测试私钥加密公钥解密
        byte[] encryptByPrivateKeyResult = RsaUtils.encryptByPrivateKey(keyPair.getPrivate(),
                content.getBytes(StandardCharsets.UTF_8));
        byte[] decryptByPublicKeyResult = RsaUtils.decryptByPublicKey(keyPair.getPublic(),
                encryptByPrivateKeyResult);
        Assert.assertEquals(content, new String(decryptByPublicKeyResult, StandardCharsets.UTF_8));
        // 测试公钥加密私钥解密
        byte[] encryptByPublicKeyResult = RsaUtils.encryptByPublicKey(keyPair.getPublic(),
                content.getBytes(StandardCharsets.UTF_8));
        byte[] decryptByPrivateKeyResult = RsaUtils.decryptByPrivateKey(keyPair.getPrivate(),
                encryptByPublicKeyResult);
        Assert.assertEquals(content, new String(decryptByPrivateKeyResult, StandardCharsets.UTF_8));
        // 测试签名
        String sign = RsaUtils.sign(content.getBytes(StandardCharsets.UTF_8), keyPair.getPrivate());
        Assert.assertTrue(RsaUtils.verify(content.getBytes(StandardCharsets.UTF_8), keyPair.getPublic(), sign));
    }
}

相关文章

  • java实现RSA与AES混合加密

    之前写过一篇在python中实现RSA和AES混合加密的文章,这次用java来实现 什么是RSA加密? 这是一种非...

  • RSA加密Java实现

  • java实现RSA加密

  • Java 实现 RSA 加密

    本文介绍 RSA 加密的原理、示例、安全性分析及 Java 语言实现。 目录 RSA 简介原理示例安全性常见用途 ...

  • Java实现ELGAMAL非对称加密算法

    ELGAMAL算法 和RSA不同的是它只提供公钥加密,它依靠BouncyCastle实现。 java实现如下: 引...

  • Java 实现 RSA 加密解密

    RSA 加密在编程中很常见,iOS 安卓要用,Java 也要用,最近因为大数据的项目要用到,就写了一份,这里备份一...

  • java实现RSA非对称加密解密

    之前写过一篇java实现AES对称加密解密在对密码加密传输的场景下 RSA非对称加密解密可能会更加适合。原理就是后...

  • RSA非对称加密

    RSA非对称加密 RSA非对称加密, 适用于Java和iOS 应用场景:用户登录时对登录密码进行加密 启动终端, ...

  • 2019-12-20

    RSA非对称加密技术(JAVA版实现加解密处理)介绍 非对称的加密技术就是指加密过程是不可逆,不能通过密文直...

  • RSA加密

    RSA加密为非对称加密实现 对称加密:加密解密使用同一个算法 非对称加密:加密和解密使用不同算法 rsa加密原理 ...

网友评论

    本文标题:Java 实现 RSA 加密

    本文链接:https://www.haomeiwen.com/subject/kilvmhtx.html