RSA加密

  • 密钥生成

使用git bash here 生成私钥,长度为1024bit

// 生成private.pem 私钥
openssl genrsa -out private.pem 1024
从私钥中提取公钥
//生成public.pem公钥
openssl rsa -pubout -in private.pem -out public.pem

1. 前端 --- jsencrypt.js

jsencrypt

☆☆☆☆☆ RSA 加密明文最大长度 117字节

☆☆☆☆☆ 解密要求秘文最大长度128字节.....

        var encryptor = new JSEncrypt();
        var publicKey = '-----BEGIN PUBLIC KEY-----xxxxxxx-----END PUBLIC KEY-----';
        encryptor.setPublicKey(publicKey);
        var rsaPassword = encryptor.encrypt('1234');

        console.log("enc:::"+rsaPassword);

        var decrypt = new JSEncrypt();
        var priKey = '-----BEGIN RSA PRIVATE KEY-----xxxxxx-----END RSA PRIVATE KEY-----';
        decrypt.setPrivateKey(priKey);
        var uncrypted = decrypt.decrypt(rsaPassword);
        console.log("unc:::"+uncrypted);

    	//jsonstr 按照key进行排序
			function jsonSort(jsonobj){
          var jsonobj = JSON.parse(jsonobj);
          let arr = [];
          for(var key in jsonobj){
              arr.push(key);
          }
          arr.sort();
          let resObj = {};
          for (var i in arr){
              resObj[arr[i]] = jsonobj[arr[i]];
          }
          return JSON.stringify(resObj);
      }

2. 服务端 --- aes rsa

package cn.xxx.xxx.utils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.lang3.StringUtils;

import java.util.Base64;

//import sun.misc.BASE64Decoder;
//import sun.misc.BASE64Encoder;

/**
* @Title: AESUtils.java
* @Package xxx
* @Description: TODO
* @author xxx
* @date 2017年9月11日 下午5:48:17
* @version V1.0
*/
public class AESUtils {


    private static final String encodeRules = "xxxxx";

    /**
* 加密
* 1.构造密钥生成器
* 2.根据ecnodeRules规则初始化密钥生成器
* 3.产生密钥
* 4.创建和初始化密码器
* 5.内容加密
* 6.返回字符串
*/
    public static String AESEncode(String content) {
        try {
            //1.构造密钥生成器,指定为AES算法,不区分大小写
            KeyGenerator keygen = KeyGenerator.getInstance("AES");
            //2.根据ecnodeRules规则初始化密钥生成器
            //生成一个128位的随机源,根据传入的字节数组
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            random.setSeed(encodeRules.getBytes());
            keygen.init(128, random);
            //3.产生原始对称密钥
            SecretKey original_key = keygen.generateKey();
            //4.获得原始对称密钥的字节数组
            byte[] raw = original_key.getEncoded();
            //5.根据字节数组生成AES密钥
            SecretKey key = new SecretKeySpec(raw, "AES");
            //6.根据指定算法AES自成密码器
            Cipher cipher = Cipher.getInstance("AES");
            //7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密解密(Decrypt_mode)操作,第二个参数为使用的KEY
            cipher.init(Cipher.ENCRYPT_MODE, key);
            //8.获取加密内容的字节数组(这里要设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码
            byte[] byte_encode = content.getBytes("utf-8");
            //9.根据密码器的初始化方式--加密:将数据加密
            byte[] byte_AES = cipher.doFinal(byte_encode);
            //10.将加密后的数据转换为字符串
            //这里用Base64Encoder中会找不到包
            //解决办法:
            //在项目的Build path中先移除JRE System Library,再添加库JRE System Library,重新编译后就一切正常了。
            String AES_encode = new String(Base64.getEncoder().encodeToString(byte_AES));
            //11.将字符串返回
            return AES_encode;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        //如果有错就返加nulll
        return null;
    }



    /**
* AES加密
* @param content 待加密的内容
* @param encryptKey 加密密钥
* @return 加密后的byte[]
* @throws Exception
*/
public static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception {
    KeyGenerator kgen = KeyGenerator.getInstance("AES");
    //        kgen.init(128, new SecureRandom(encryptKey.getBytes()));
    kgen.init(128);
    
    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"));
    
    return cipher.doFinal(content.getBytes("utf-8"));
}

/**
* 解密
* 解密过程:
* 1.同加密1-4步
* 2.将加密后的字符串反纺成byte[]数组
* 3.将加密内容解密
*/
public static String AESDecode(String content) {
    try {
        //1.构造密钥生成器,指定为AES算法,不区分大小写
        KeyGenerator keygen = KeyGenerator.getInstance("AES");
        //2.根据ecnodeRules规则初始化密钥生成器
        //生成一个128位的随机源,根据传入的字节数组
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
        random.setSeed(encodeRules.getBytes());
        keygen.init(128, random);
        //3.产生原始对称密钥
        SecretKey original_key = keygen.generateKey();
        //4.获得原始对称密钥的字节数组
        byte[] raw = original_key.getEncoded();
        //5.根据字节数组生成AES密钥
        SecretKey key = new SecretKeySpec(raw, "AES");
        //6.根据指定算法AES自成密码器
        Cipher cipher = Cipher.getInstance("AES");
        //7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密(Decrypt_mode)操作,第二个参数为使用的KEY
        cipher.init(Cipher.DECRYPT_MODE, key);
        //8.将加密并编码后的内容解码成字节数组
        byte[] byte_content =  Base64.getDecoder().decode(content);
        /*
        * 解密
        */
        byte[] byte_decode = cipher.doFinal(byte_content);
        String AES_decode = new String(byte_decode, "utf-8");
        return AES_decode;
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
        e.printStackTrace();
    } catch (BadPaddingException e) {
        e.printStackTrace();
    }
    //如果有错就返加nulll
    return null;
}


/**
* AES解密
* @param encryptBytes 待解密的byte[]
* @param decryptKey 解密密钥
* @return 解密后的String
* @throws Exception
*/
public static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception {
    KeyGenerator kgen = KeyGenerator.getInstance("AES");
    //        kgen.init(128, new SecureRandom(decryptKey.getBytes()));
    kgen.init(128);
    
    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
    cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"));
    byte[] decryptBytes = cipher.doFinal(encryptBytes);
    
    return new String(decryptBytes);
}

/**
* base 64 加密
* @param bytes 待编码的byte[]
* @return 编码后的base 64 code
*/
public static String base64Encode(byte[] bytes){
    return Base64.getEncoder().encodeToString(bytes);
}

/**
* base 64 解密
* @param base64Code 待解码的base 64 code
* @return 解码后的byte[]
* @throws Exception
*/
public static byte[] base64Decode(String base64Code) throws Exception{

    return StringUtils.isEmpty(base64Code) ? null :  Base64.getDecoder().decode(base64Code);
}

/**
* 将base 64 code AES解密
* @param encryptStr 待解密的base 64 code
* @param decryptKey 解密密钥
* @return 解密后的string
* @throws Exception
*/
public static String aesDecrypt(String encryptStr, String decryptKey) throws Exception {
    return StringUtils.isEmpty(encryptStr) ? null : aesDecryptByBytes(base64Decode(encryptStr), decryptKey);
}

/**
* AES加密为base 64 code
* @param content 待加密的内容
* @param encryptKey 加密密钥
* @return 加密后的base 64 code
* @throws Exception
*/
public static String aesEncrypt(String content, String encryptKey) throws Exception {
    return base64Encode(aesEncryptToBytes(content, encryptKey));
}

}

package cn.xxx.xxx.utils;

import lombok.Data;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

public class RSAUtils {

    @Data
    public static class RSAKeyPair {
        String publicKey;
        String privateKey;
    }

    public static RSAKeyPair getKeyPair() throws Exception{
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
        keyPairGen.initialize(1024, new SecureRandom());
        KeyPair keyPair = keyPairGen.generateKeyPair();
        PrivateKey privateKey = keyPair.getPrivate();
        PublicKey publicKey = keyPair.getPublic();
        String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
        String privateKeyString = new String(Base64.encodeBase64(privateKey.getEncoded()));
        RSAKeyPair rsaKeyPair = new RSAKeyPair();
        rsaKeyPair.setPublicKey(publicKeyString);
        rsaKeyPair.setPrivateKey(privateKeyString);
        return rsaKeyPair;
    }

    public static String encrypt(String str, String publicKey) throws Exception {
        byte[] decoded = Base64.decodeBase64(publicKey);
        RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA")
                .generatePublic(new X509EncodedKeySpec(decoded));
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        return Base64.encodeBase64String(cipher.doFinal(str.getBytes(StandardCharsets.UTF_8)));
    }

    public static String decrypt(String str, String privateKey) throws Exception {
        byte[] inputByte = Base64.decodeBase64(str.getBytes(StandardCharsets.UTF_8));
        byte[] decoded = Base64.decodeBase64(privateKey);
        PrivateKey priKey = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, priKey);
        return new String(cipher.doFinal(inputByte));
    }
    public static String sign(String plainText, String privateKey) throws Exception {

        Signature privateSignature = Signature.getInstance("SHA256withRSA");
        privateSignature.initSign(getPrivate(privateKey));
        privateSignature.update(plainText.getBytes("UTF-8"));

        byte[] signature = privateSignature.sign();

        return Base64.encodeBase64String(signature);
    }
    public static boolean verify(String plainText, String signature, String publicKey) throws Exception {
        Signature publicSignature = Signature.getInstance("SHA256withRSA");
        publicSignature.initVerify(getPublic(publicKey));
        publicSignature.update(plainText.getBytes("UTF-8"));

        byte[] signatureBytes = Base64.decodeBase64(signature);

        return publicSignature.verify(signatureBytes);
    }
}

    @Test
    public void testRsa() throws Exception {

        RSAUtils.RSAKeyPair keyPair = RSAUtils.getKeyPair();
        String realVal = "1234333333";

        String encodeval = RSAUtils.encrypt("1234333333", keyPair.getPublicKey());
        System.out.println("encodeVal:::" + encodeval);
        String decodeval = RSAUtils.decrypt(encodeval, keyPair.getPrivateKey());
        System.out.println("decodeval:::" + decodeval);

        String deval = RSAUtils.decrypt(encodeval, keyPair.getPrivateKey());
        System.out.println("deval:::"+deval);
        boolean istrue = realVal.equals(deval);
        System.out.println(istrue);

        String abcdefghigklmn = RSAUtils.sign("abcdefghigklmn", keyPair.getPrivateKey());
        System.out.println("sign:"+abcdefghigklmn);
        boolean xxxxx = RSAUtils.verify("abcdefghigklmn", abcdefghigklmn, keyPair.getPublicKey());
        System.out.println("is:"+xxxxx);
    }
https://www.npmjs.com/package/jsencrypt
// Sign with the private key...
var sign = new JSEncrypt();
sign.setPrivateKey($('#privkey').val());
var signature = sign.sign($('#input').val(), CryptoJS.SHA256, "sha256");

// Verify with the public key...
var verify = new JSEncrypt();
verify.setPublicKey($('#pubkey').val());
var verified = verify.verify($('#input').val(), signature, CryptoJS.SHA256);

// Now a simple check to see if the round-trip worked.
if (verified) {
  alert('It works!!!');
}
else {
  alert('Something went wrong....');
}

posted @ 2024-12-17 15:52  若云  阅读(26)  评论(0)    收藏  举报