密码技术学习(6.2.2)-非对称加密在Java中的使用-RSA(典型非对称加密算法)

文章目录

RSA(典型非对称加密算法)

RSACoder工具类

RSACoderTest

参考资料

本系列其他文章


RSA(典型非对称加密算法)

之前介绍了DH算法,现在我们来介绍RSA算法。

在公开密钥密码体制中,加密密钥(即公开密钥)PK是公开信息,而解密密钥(即秘密密钥)SK是需要保密的。加密算法E和解密算法D也都是公开的。虽然解密密钥SK是由公开密钥PK决定的,由于无法计算出大数n的欧拉函数phi(N),所以不能根据PK计算出SK。百度百科

基本上所有的非对称加密都是基于数学难题(基本上无解),而RSA算法是基于大数因数分解难题。即将两个大素数相乘很容易,但是想要将相乘的结果分解为两个大素数是非常困难(几乎不可能)。

RSACoder工具类

import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.Cipher;

/**
 * RSA 编码组件
 * 
 * @author shaozuo
 * @date 2018/08/01
 */
public final class RSACoder {

    public static final String ALGORITHM_NAME = "RSA";

    private RSACoder() {

    }

    private static final int KEY_SIZE = 512;
    private static final String PUBLIC_KEY = "public_key";
    private static final String PRIVATE_KEY = "private_key";

    /**
     * 初始化公钥
     * 
     * @return Map 密钥map
     * @throws Exception
     */
    public static Map initKey() throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM_NAME);
        keyPairGenerator.initialize(KEY_SIZE);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();

        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

        Map keyMap = new HashMap<>();
        keyMap.put(PUBLIC_KEY, publicKey);
        keyMap.put(PRIVATE_KEY, privateKey);
        return keyMap;
    }

    public static byte[] getPrivateKey(Map keyMap) {
        Key key = (Key) keyMap.get(PRIVATE_KEY);
        return key.getEncoded();
    }

    public static byte[] getPublicKey(Map keyMap) {
        Key key = (Key) keyMap.get(PUBLIC_KEY);
        return key.getEncoded();
    }

    /**
     * 使用公钥加密数据
     * 
     * @param data
     *            待加密数据
     * @param encodedPublicKey
     *            公钥
     * @return
     * @throws GeneralSecurityException
     */
    public static byte[] encyptByPublicKey(byte[] data, byte[] encodedPublicKey)
            throws GeneralSecurityException {
        X509EncodedKeySpec encodedKeySpec = new X509EncodedKeySpec(encodedPublicKey);
        KeyFactory factory = KeyFactory.getInstance(ALGORITHM_NAME);
        PublicKey publicKey = factory.generatePublic(encodedKeySpec);

        Cipher cipher = Cipher.getInstance(factory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return cipher.doFinal(data);
    }

    /**
     * 使用私钥加密数据
     * 
     * @param data
     *            待加密数据
     * @param encodedPublicKey
     *            私钥
     * @return
     * @throws GeneralSecurityException
     */
    public static byte[] encyptByPrivateKey(byte[] data, byte[] encodedPrivateKey)
            throws GeneralSecurityException {
        PKCS8EncodedKeySpec encodedKeySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);
        KeyFactory factory = KeyFactory.getInstance(ALGORITHM_NAME);
        PrivateKey privateKey = factory.generatePrivate(encodedKeySpec);

        Cipher cipher = Cipher.getInstance(factory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        return cipher.doFinal(data);
    }

    /**
     * 使用公钥解密数据
     * 
     * @param data
     *            待解密数据
     * @param encodedPublicKey
     *            公钥
     * @return
     * @throws GeneralSecurityException
     */
    public static byte[] decyptByPublicKey(byte[] data, byte[] encodedPublicKey)
            throws GeneralSecurityException {
        X509EncodedKeySpec encodedKeySpec = new X509EncodedKeySpec(encodedPublicKey);
        KeyFactory factory = KeyFactory.getInstance(ALGORITHM_NAME);
        PublicKey publicKey = factory.generatePublic(encodedKeySpec);

        Cipher cipher = Cipher.getInstance(factory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
        return cipher.doFinal(data);
    }

    /**
     * 使用私钥解密数据
     * 
     * @param data
     *            待解密数据
     * @param encodedPublicKey
     *            私钥
     * @return
     * @throws GeneralSecurityException
     */
    public static byte[] decyptByPrivateKey(byte[] data, byte[] encodedPrivateKey)
            throws GeneralSecurityException {
        PKCS8EncodedKeySpec encodedKeySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);
        KeyFactory factory = KeyFactory.getInstance(ALGORITHM_NAME);
        PrivateKey privateKey = factory.generatePrivate(encodedKeySpec);

        Cipher cipher = Cipher.getInstance(factory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return cipher.doFinal(data);
    }

}

RSACoderTest

import static org.junit.Assert.assertEquals;

import java.util.Map;

import org.apache.commons.codec.binary.Base64;
import org.junit.Before;
import org.junit.Test;

public class RSACoderTest {
    // 公钥
    private byte[] publicKey;
    // 私钥
    private byte[] privateKey;

    String rawStrForPri = "RSA 私钥加密-公钥解密";
    String rawStrForPub = "RSA 公钥加密-私钥解密";

    @Before
    public final void initKey() throws Exception {
        Map keyMap = RSACoder.initKey();
        publicKey = RSACoder.getPublicKey(keyMap);
        privateKey = RSACoder.getPrivateKey(keyMap);

        System.out.println("公钥: " + Base64.encodeBase64String(publicKey));
        System.out.println("私钥: " + Base64.encodeBase64String(privateKey));

    }

    @Test
    public void test() throws Exception {
        System.out.println("待加密数据:" + rawStrForPri);
        System.out.println("原文:" + rawStrForPri);

        byte[] encodeData = RSACoder.encyptByPrivateKey(rawStrForPri.getBytes(), privateKey);
        System.out.println("加密数据: " + Base64.encodeBase64String(encodeData));

        byte[] decodeData = RSACoder.decyptByPublicKey(encodeData, publicKey);
        String output = new String(decodeData);
        System.out.println("解密数据:" + output);

        assertEquals(rawStrForPri, output);

        // -----公钥加密
        System.out.println("待加密数据:" + rawStrForPub);
        System.out.println("原文:" + rawStrForPub);

        encodeData = RSACoder.encyptByPublicKey(rawStrForPub.getBytes(), publicKey);
        System.out.println("加密数据: " + Base64.encodeBase64String(encodeData));

        decodeData = RSACoder.decyptByPrivateKey(encodeData, privateKey);
        output = new String(decodeData);
        System.out.println("解密数据:" + output);

        assertEquals(rawStrForPub, output);
    }
}

参考资料

关于本章内容,参考了一下书籍和文章

  1. Java加密与解密的艺术
  2. 图解密码技术-第二版 第三版
  3. RSA算法-百度百科

本系列其他文章

密码技术学习系列文章

你可能感兴趣的:(信息安全)