RSA加密与签名的区别

文章目录

  • 一、签名验签原理
  • 二 RSAUtils 工具类
  • 三、通过x509Certificate来获取CA证书的基本信息
  • 四、 通过公钥获取公钥长度

一、签名验签原理

签名的本质其实就是加密,但是由于签名无需还原成明文,因此可以在加密前进行哈希处理。所以签名其实就是哈希+加密,而验签就是哈希+解密+比较。

签名过程:对明文做哈希,拼接头信息,用私钥进行加密,得到签名。

验签过程:用公钥解密签名,然后去除头信息,对明文做哈希,比较2段哈希值是否相同,相同则验签成功。
代码编写: Cipher 用于加密 Signature 用于签名

二 RSAUtils 工具类

package com.example.tr34.application.utils;

import android.util.Base64;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

/**
 * date:2020/9/4 0004
 * author:wsm (Administrator)
 * funcation: 私钥有问题,base64解码失败
 */

public class RSAUtils {
    private static String RSA = "RSA";
    /**
     * **
     * RSA最大加密大小
     */
    private final static int MAX_ENCRYPT_BLOCK = 117;

    /**
     * **
     * RSA最大解密大小
     */
    private final static int MAX_DECRYPT_BLOCK = 128;

    /**
     * 随机生成RSA密钥对(默认密钥长度为1024)
     *
     * @return
     */
    public static KeyPair generateRSAKeyPair() {
        return generateRSAKeyPair(1024);
    }

    /**
     * 随机生成RSA密钥对
     *
     * @param keyLength 密钥长度,范围:512~2048
* 一般1024 * @return */ public static KeyPair generateRSAKeyPair(int keyLength) { try { KeyPairGenerator kpg = KeyPairGenerator.getInstance(RSA); kpg.initialize(keyLength); return kpg.genKeyPair(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return null; } } /** * 用公钥加密
* 每次加密的字节数,不能超过密钥的长度值减去11 * * @param data 需加密数据的byte数据 * @param publicKey 公钥 * @return 加密后的byte型数据 */ public static byte[] encryptData(byte[] data, PublicKey publicKey) { try { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); // 编码前设定编码方式及密钥 cipher.init(Cipher.ENCRYPT_MODE, publicKey); // 传入编码数据并返回编码结果 return cipher.doFinal(data); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 用私钥解密 * * @param encryptedData 经过encryptedData()加密返回的byte数据 * @param privateKey 私钥 * @return */ public static byte[] decryptData(byte[] encryptedData, PrivateKey privateKey) { try { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE, privateKey); return cipher.doFinal(encryptedData); } catch (Exception e) { return null; } } /** * 通过公钥byte[](publicKey.getEncoded())将公钥还原,适用于RSA算法 * * @param keyBytes * @return * @throws NoSuchAlgorithmException * @throws InvalidKeySpecException */ public static PublicKey getPublicKey(byte[] keyBytes) throws NoSuchAlgorithmException, InvalidKeySpecException { X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(RSA); PublicKey publicKey = keyFactory.generatePublic(keySpec); return publicKey; } /** * 通过私钥byte[]将公钥还原,适用于RSA算法 * * @param keyBytes * @return * @throws NoSuchAlgorithmException * @throws InvalidKeySpecException */ public static PrivateKey getPrivateKey(byte[] keyBytes) throws NoSuchAlgorithmException, InvalidKeySpecException { PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(RSA); PrivateKey privateKey = keyFactory.generatePrivate(keySpec); return privateKey; } /** * 使用N、e值还原公钥 * * @param modulus * @param publicExponent * @return * @throws NoSuchAlgorithmException * @throws InvalidKeySpecException */ public static PublicKey getPublicKey(String modulus, String publicExponent) throws NoSuchAlgorithmException, InvalidKeySpecException { BigInteger bigIntModulus = new BigInteger(modulus); BigInteger bigIntPrivateExponent = new BigInteger(publicExponent); RSAPublicKeySpec keySpec = new RSAPublicKeySpec(bigIntModulus, bigIntPrivateExponent); KeyFactory keyFactory = KeyFactory.getInstance(RSA); PublicKey publicKey = keyFactory.generatePublic(keySpec); return publicKey; } /** * 使用N、d值还原私钥 * * @param modulus * @param privateExponent * @return * @throws NoSuchAlgorithmException * @throws InvalidKeySpecException */ public static PrivateKey getPrivateKey(String modulus, String privateExponent) throws NoSuchAlgorithmException, InvalidKeySpecException { BigInteger bigIntModulus = new BigInteger(modulus); BigInteger bigIntPrivateExponent = new BigInteger(privateExponent); RSAPublicKeySpec keySpec = new RSAPublicKeySpec(bigIntModulus, bigIntPrivateExponent); KeyFactory keyFactory = KeyFactory.getInstance(RSA); PrivateKey privateKey = keyFactory.generatePrivate(keySpec); return privateKey; } /** * 从字符串中加载公钥 * * @param publicKeyStr 公钥数据字符串 * @throws Exception 加载公钥时产生的异常 */ public static PublicKey loadPublicKey(String publicKeyStr) throws Exception { try { byte[] buffer = Base64.decode(publicKeyStr,Base64.DEFAULT); KeyFactory keyFactory = KeyFactory.getInstance(RSA); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer); return (RSAPublicKey) keyFactory.generatePublic(keySpec); } catch (NoSuchAlgorithmException e) { throw new Exception("无此算法"); } catch (InvalidKeySpecException e) { throw new Exception("公钥非法"); } catch (NullPointerException e) { throw new Exception("公钥数据为空"); } } /** * 从字符串中加载私钥
* 加载时使用的是PKCS8EncodedKeySpec(PKCS#8编码的Key指令)。 * * @param privateKeyStr * @return * @throws Exception */ public static PrivateKey loadPrivateKey(String privateKeyStr) throws Exception { try { byte[] buffer = Base64.decode(privateKeyStr,Base64.DEFAULT); // X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer); KeyFactory keyFactory = KeyFactory.getInstance(RSA); return (RSAPrivateKey) keyFactory.generatePrivate(keySpec); } catch (NoSuchAlgorithmException e) { throw new Exception("无此算法"); } catch (InvalidKeySpecException e) { throw new Exception("私钥非法"); } catch (NullPointerException e) { throw new Exception("私钥数据为空"); } } /** * 用公钥分段加密
* 每次加密的字节数,不能超过密钥的长度值减去11 * * @param data 需加密数据的byte数据 * @param publicKey 公钥 * @return 加密后的byte型数据 */ public static byte[] PublicSubData(byte[] data, PublicKey publicKey) { try { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); // 编码前设定编码方式及密钥 cipher.init(Cipher.ENCRYPT_MODE, publicKey); // 传入编码数据并返回编码结果 // return cipher.doFinal(data); int inputLen = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 对数据分段加密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); } else { cache = cipher.doFinal(data, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_ENCRYPT_BLOCK; } byte[] decryptedData = out.toByteArray(); out.close(); return decryptedData; } catch (Exception e) { e.printStackTrace(); return null; } } /** * 用私钥分段解密 * * @param encryptedData 经过encryptedData()加密返回的byte数据 * @param privateKey 私钥 * @return */ public static byte[] PrivateSubData(byte[] encryptedData, PrivateKey privateKey) { try { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE, privateKey); // return cipher.doFinal(encryptedData); // 返回UTF-8编码的解密信息 int inputLen = encryptedData.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 对数据分段解密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_DECRYPT_BLOCK) { cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK); } else { cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_DECRYPT_BLOCK; } byte[] decryptedData = out.toByteArray(); out.close(); return decryptedData; } catch (Exception e) { return null; } } /** * 从文件中输入流中加载公钥 * * @param in 公钥输入流 * @throws Exception 加载公钥时产生的异常 */ public static PublicKey loadPublicKey(InputStream in) throws Exception { try { return loadPublicKey(readKey(in)); } catch (IOException e) { throw new Exception("公钥数据流读取错误"); } catch (NullPointerException e) { throw new Exception("公钥输入流为空"); } } /** * 从文件中加载私钥 * * @param in 私钥文件名 * @return 是否成功 * @throws Exception */ public static PrivateKey loadPrivateKey(InputStream in) throws Exception { try { return loadPrivateKey(readKey(in)); } catch (IOException e) { throw new Exception("私钥数据读取错误"); } catch (NullPointerException e) { throw new Exception("私钥输入流为空"); } } /** * 读取密钥信息 * * @param in * @return * @throws IOException */ private static String readKey(InputStream in) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(in)); String readLine = null; StringBuilder sb = new StringBuilder(); while ((readLine = br.readLine()) != null) { if (readLine.charAt(0) == '-') { continue; } else { sb.append(readLine); sb.append('\r'); } } return sb.toString(); } /** * 打印公钥信息 * * @param publicKey */ public static void printPublicKeyInfo(PublicKey publicKey) { RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey; System.out.println("----------RSAPublicKey----------"); System.out.println("Modulus.length=" + rsaPublicKey.getModulus().bitLength()); System.out.println("Modulus=" + rsaPublicKey.getModulus().toString()); System.out.println("PublicExponent.length=" + rsaPublicKey.getPublicExponent().bitLength()); System.out.println("PublicExponent=" + rsaPublicKey.getPublicExponent().toString()); } public static void printPrivateKeyInfo(PrivateKey privateKey) { RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) privateKey; System.out.println("----------RSAPrivateKey ----------"); System.out.println("Modulus.length=" + rsaPrivateKey.getModulus().bitLength()); System.out.println("Modulus=" + rsaPrivateKey.getModulus().toString()); System.out.println("PrivateExponent.length=" + rsaPrivateKey.getPrivateExponent().bitLength()); System.out.println("PrivatecExponent=" + rsaPrivateKey.getPrivateExponent().toString()); } }

三、通过x509Certificate来获取CA证书的基本信息

     //创建X509工厂类
     CertificateFactory cf = CertificateFactory.getInstance("X.509");
     //创建证书对象
     X509Certificate oCert = (X509Certificate)cf.generateCertificate(inStream);// inStream证书的传入数据
     inStream.close();
     SimpleDateFormat dateformat = new SimpleDateFormat("yyyy/MM/dd");
      String info = null;
     //获得证书版本
      info = String.valueOf(oCert.getVersion());
     System.out.println("证书版本:"+info);
     //获得证书序列号
      info = oCert.getSerialNumber().toString(16);
     System.out.println("证书序列号:"+info);
     //获得证书有效期
      Date beforedate = oCert.getNotBefore();
      info = dateformat.format(beforedate);
     System.out.println("证书生效日期:"+info);
      Date afterdate = oCert.getNotAfter();
      info = dateformat.format(afterdate);
     System.out.println("证书失效日期:"+info);
     //获得证书主体信息
      info = oCert.getSubjectDN().getName();
     System.out.println("证书拥有者:"+info);
     //获得证书颁发者信息
      info = oCert.getIssuerDN().getName();
     System.out.println("证书颁发者:"+info);
     //获得证书签名算法名称
      info = oCert.getSigAlgName();
     System.out.println("证书签名算法:"+info);
 
 
      byte[] byt = oCert.getExtensionValue("1.2.86.11.7.9");
      String strExt = new String(byt);
     System.out.println("证书扩展域:" + strExt);
      byt = oCert.getExtensionValue("1.2.86.11.7.1.8");
      String strExt2 = new String(byt);
     System.out.println("证书扩展域2:" + strExt2);

四、 通过公钥获取公钥长度

通过X509Certificate.getPublicKey 获取公钥

      /**
     * Gets the key length of supported keys
     * @param pk PublicKey used to derive the keysize
     * @return -1 if key is unsupported, otherwise a number >= 0. 0 usually means the length can not be calculated,
     * for example if the key is an EC key and the "implicitlyCA" encoding is used.
     */
    public static int getKeyLength(final PublicKey pk) {
        int len = -1;
        if (pk instanceof RSAPublicKey) {
            final RSAPublicKey rsapub = (RSAPublicKey) pk;
            len = rsapub.getModulus().bitLength();
        } else if (pk instanceof JCEECPublicKey) {
            final JCEECPublicKey ecpriv = (JCEECPublicKey) pk;
            final org.bouncycastle.jce.spec.ECParameterSpec spec = ecpriv.getParameters();
            if (spec != null) {
                len = spec.getN().bitLength();
            } else {
                // We support the key, but we don't know the key length
                len = 0;
            }
        } else if (pk instanceof ECPublicKey) {
            final ECPublicKey ecpriv = (ECPublicKey) pk;
            final java.security.spec.ECParameterSpec spec = ecpriv.getParams();
            if (spec != null) {
                len = spec.getOrder().bitLength(); // does this really return something we expect?
            } else {
                // We support the key, but we don't know the key length
                len = 0;
            }
        } else if (pk instanceof DSAPublicKey) {
            final DSAPublicKey dsapub = (DSAPublicKey) pk;
            if ( dsapub.getParams() != null ) {
                len = dsapub.getParams().getP().bitLength();
            } else {
                len = dsapub.getY().bitLength();
            }
        }
        return len;
    }

你可能感兴趣的:(数据结构,算法)