RSA 公钥加密-私钥解密、私钥加密-公钥解密、数字签名、数字验签

数字签名和加密的区别

数字签名和验证:

发送报文时,发送方用一个hash算法从报文中产生固定长度的报文摘要,然后利用自己的私钥对这个摘要进行加密,这个过程就叫签名。这个加密后的摘要作为报文的数字签名和报文一起发送给接收方,接收方用发送方的公钥解密被加密的摘要(报文附加的数字签名)得到结果A,然后用于发送方一样的hash算法从接收到的原始报文中算出报文摘要B。最后,把A和B作比较。如果相同,那么接收方就能确认该数字签名是发送方的。

数字签名的功能:

1、对签名者进行身份认证;

2、保证信息的完整性(在交易过程中,没有被篡改)

3、防止交易中的抵赖发生(签名者无法否认信息是由自己发出的)

 加密和解密:

发送方利用接收方的公钥对要发送的明文进行加密,接受方利用自己的私钥进行解密,其中公钥和私钥匙相对的,任何一个作为公钥,则另一个就为私钥。

加密的功能:

重点在于“数据的安全性”,可以防止数据被监听攻击。

import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;


public class RSASignUtil {

    public static final String CHARSET = "UTF-8";
    public static final String RSA = "RSA";

    //签名算法采用SHA256WithRSA,(也可使用MD5withRSA的算法方式)
    public static final String SIGN_ALGORITHM = "SHA256WithRSA"; 

    //采用长度为2048bits的pkcs8格式的秘钥,(一般长度为512-2048)
    public static final int KEY_SIZE = 2048; 

    private static String publicKeyString;
    private static String privateKeyString;

    //加密的数据
    private static String str = "111222333444-1 111222333444-2 111222333444-3 111222333444-4 111222333444-5 "
            + "111222333444-6 111222333444-7 111222333444-8 111222333444-9 111222333444-10 "
            + "111222333444-11 111222333444-12 111222333444-13 111222333444-14 111222333444-15 "
            + "111222333444-16 111222333444-17 111222333444-18 111222333444-19 111222333444-20";

    static {
        Map<String, String> keyMap = createKeys(KEY_SIZE);
        publicKeyString = keyMap.get("publicKey");
        privateKeyString = keyMap.get("privateKey");
        System.out.println("公钥: \n\r" + publicKeyString);
        System.out.println("私钥: \n\r" + privateKeyString);
    }

    public static void main(String[] args) throws Exception {
        //公钥加密——私钥解密
        pub_pri_test();
        //私钥加密——公钥解密
        pri_pub_test();
        //私钥签名-公钥验签
        signTest();
    }

    /**
     * 公钥加密——私钥解密
     */
    private static void pub_pri_test() throws InvalidKeySpecException, NoSuchAlgorithmException {
        System.out.println("\n公钥加密——私钥解密------------------------------------------------------");
        System.out.println("\r加密前的数据:\r\n" + str + "  \n 加密前的数据大小:" + str.getBytes().length);
        String encodedData = publicEncrypt(str);
        System.out.println("公钥加密后的数据:\r\n" + encodedData);
        String decodedData = privateDecrypt(encodedData);
        System.out.println("私钥解密后的数据: \r\n" + decodedData + "\n");
    }

    /**
     * 私钥加密——公钥解密
     */
    private static void pri_pub_test() throws InvalidKeySpecException, NoSuchAlgorithmException {
        System.out.println("\n私钥加密——公钥解密------------------------------------------------------");
        System.out.println("\r加密前的数据:\r\n" + str + "  \n 加密前的数据大小:" + str.getBytes().length);
        String encryptData = privateEncrypt(str);
        System.out.println("加密后的数据:\r\n" + encryptData);
        String decryptData = publicDecrypt(encryptData);
        System.out.println("解密后的数据: \r\n" + decryptData + "\n");
    }

    /**
     * 私钥签名-公钥验签
     */
    private static void signTest() {
        System.out.println("\r签名前的数据:\r\n" + str);
        String sign = sign(str);
        System.out.println("签名后的数据 : \n" + sign);
        boolean validation = verify(str, sign);
        System.out.println("验签结果 : \n" + validation);
    }

    /**
     * 签名
     *
     * @param content
     */
    public static String sign(String content) {
        try {
            RSAPrivateKey rsaPrivateKey = getPrivateKey(privateKeyString);
            //2、执行签名
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
            KeyFactory keyFactory = KeyFactory.getInstance(RSA);
            PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
            Signature signature = Signature.getInstance(SIGN_ALGORITHM);
            signature.initSign(privateKey);
            signature.update(content.getBytes());
            byte[] result = signature.sign();
            String resultData = Base64.encodeBase64URLSafeString(result);
            return resultData;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 验签
     *
     * @param content 签名前的数据
     * @param signData 签名后的数据
     * @return
     */
    public static boolean verify(String content, String signData) {
        try {
            RSAPublicKey rsaPublicKey = getPublicKey(publicKeyString);
            //3、验证签名
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
            KeyFactory keyFactory = KeyFactory.getInstance(RSA);
            PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
            Signature signature = Signature.getInstance(SIGN_ALGORITHM);
            signature.initVerify(publicKey);
            signature.update(content.getBytes());
            boolean result = signature.verify(Base64.decodeBase64(signData));
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 公钥加密
     * @param content 需要加密的内容
     * @return
     */
    public static String publicEncrypt(String content) {
        Cipher cipher = null;
        try {
            cipher = Cipher.getInstance(RSA);
            RSAPublicKey publicKey = getPublicKey(publicKeyString);
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, content.getBytes(CHARSET), publicKey.getModulus().bitLength()));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 私钥解密
     * @param content 需要解密的内容
     * @return
     */
    public static String privateDecrypt(String content) {
        try {
            Cipher cipher = Cipher.getInstance(RSA);
            RSAPrivateKey privateKey = getPrivateKey(privateKeyString);
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(content), privateKey.getModulus().bitLength()), CHARSET);
        } catch (Exception e) {
            throw new RuntimeException("解密字符串[" + content + "]时遇到异常", e);
        }
    }

    /**
     * 私钥加密
     * @param content 需要加密的内容
     */
    public static String privateEncrypt(String content) {
        try {
            Cipher cipher = Cipher.getInstance(RSA);
            RSAPrivateKey privateKey = getPrivateKey(privateKeyString);
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, content.getBytes(CHARSET), privateKey.getModulus().bitLength()));
        } catch (Exception e) {
            throw new RuntimeException("加密字符串[" + content + "]时遇到异常", e);
        }
    }

    /**
     * 公钥解密
     * @param content 需要解密的内容
     * @return
     */
    public static String publicDecrypt(String content) {
        try {
            Cipher cipher = Cipher.getInstance(RSA);
            RSAPublicKey publicKey = getPublicKey(publicKeyString);
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(content), publicKey.getModulus().bitLength()), CHARSET);
        } catch (Exception e) {
            throw new RuntimeException("解密字符串[" + content + "]时遇到异常", e);
        }
    }

    /**
     * 长度为keySize的密钥
     *
     * @param keySize
     * @return
     */
    private static Map<String, String> createKeys(int keySize) {
        //为RSA算法创建一个KeyPairGenerator对象
        KeyPairGenerator kpg;
        try {
            kpg = KeyPairGenerator.getInstance(RSA);
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalArgumentException("No such algorithm-->[" + RSA + "]");
        }

        //初始化KeyPairGenerator对象,密钥长度
        kpg.initialize(keySize);
        //生成密匙对
        KeyPair keyPair = kpg.generateKeyPair();
        //得到公钥
        Key publicKey = keyPair.getPublic();
        String publicKeyStr = Base64.encodeBase64URLSafeString(publicKey.getEncoded());
        //得到私钥
        Key privateKey = keyPair.getPrivate();
        String privateKeyStr = Base64.encodeBase64URLSafeString(privateKey.getEncoded());
        Map<String, String> keyPairMap = new HashMap<String, String>();
        keyPairMap.put("publicKey", publicKeyStr);
        keyPairMap.put("privateKey", privateKeyStr);

        return keyPairMap;
    }

    /**
     * 得到公钥
     *
     * @param publicKey 密钥字符串(经过base64编码)
     * @throws Exception
     */
    private static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
        //通过X509编码的Key指令获得公钥对象
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
        RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
        return key;
    }

    /**
     * 得到私钥
     *
     * @param privateKey 密钥字符串(经过base64编码)
     * @throws Exception
     */
    private static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
        //通过PKCS#8编码的Key指令获得私钥对象
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
        RSAPrivateKey key = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
        return key;
    }

    private static byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas, int keySize) {
        int maxBlock = 0;
        if (opmode == Cipher.DECRYPT_MODE) {
            maxBlock = keySize / 8;
        } else {
            maxBlock = keySize / 8 - 11;
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] buff;
        int i = 0;
        try {
            while (datas.length > offSet) {
                if (datas.length - offSet > maxBlock) {
                    buff = cipher.doFinal(datas, offSet, maxBlock);
                } else {
                    buff = cipher.doFinal(datas, offSet, datas.length - offSet);
                }
                out.write(buff, 0, buff.length);
                i++;
                offSet = i * maxBlock;
            }
        } catch (Exception e) {
            throw new RuntimeException("加解密阀值为[" + maxBlock + "]的数据时发生异常", e);
        }
        byte[] resultDatas = out.toByteArray();
        try {
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return resultDatas;
    }


}

 

jar包依赖:

<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
  <groupId>commons-codec</groupId>
  <artifactId>commons-codec</artifactId>
  <version>1.10</version>
</dependency>

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值