今天实现了下AES和RSA加密解密,主要的功能是对前后端交互数据进行加密解密,为什么要用到两个算法呢,首先RSA默认的话加密长度是有限的100多个byte吧大约,并且需要公钥私钥,而AES加密没有限制只需要一个key就可以,所以我们使用AES来进行数据的加解密,那么Key传递是不是会暴露,所以使用RSA对Key进行加密,前端生成RSA的公钥私钥,后端生成AES的key,前端把公钥直接发给后端,后端使用公钥将key进行加密,前端解出来key,然后使用AES对数据加密,文件也可以!

注意:这里angular使用的是Buffer来输入输出的,也就是字节数组!

1:angular加密解密环境安装

下载crypto-js、jsencrypt

# crypto-js
npm install crypto-js
npm install --save @types/crypto-js
npm i @types/node
#更新npm,下载完crypto-js提示让更新
npm install -g npm
npm i --save-dev @types/node

#jsencrypt
npm install --save jsencrypt

#Base64编码的jar
<dependency>
  <groupId>commons-codec</groupId>
  <artifactId>commons-codec</artifactId>
  <version>1.13</version>
</dependency>

2、Angular前端:crypto实现 AES加密

AESUtils

import {AES, enc, lib, mode, pad} from 'crypto-js';
import {Buffer} from 'buffer';

export class AESUtils {
  /**
   * @param buf 字节数组
   * @param key key
   *
   * 传入字节数组和key,返回加密后的字节数组
   */
  public static encrypt(buf: Buffer,key:string): Buffer {
    let key16 = enc.Utf8.parse(key);          //将key转成16进制,如果不转解密也不能转并且加密后的数组动态的(如果有,解密必须有)
    var options = {
      mode: mode.ECB,     //模式
      padding: pad.Pkcs7  //补码方式
    };
    var encryptedData = AES.encrypt(lib.WordArray.create(buf), key16, options);  //加密
    return new Buffer(encryptedData.toString(), 'base64');  //解密后是base64的字符串,转为buff(字节数组)返回
  }

  public static decrypt(buf: Buffer,key:string): Buffer {
    let data = buf.toString('base64');  //将字节转为base64字符
    let key16 = enc.Utf8.parse(key);
    var options = {
      mode: mode.ECB,     //模式
      padding: pad.Pkcs7  //补码方式
    };
    var decryptedData = AES.decrypt(data, key16, options);  //解密
    return new Buffer(enc.Base64.stringify(decryptedData), 'base64');    //返回字节数组
  }
}

JAVA

    private static String enCode(String key, byte[] content) throws Exception{
        SecretKeySpec skey = new SecretKeySpec(key.getBytes(), "AES");
        Cipher cipher = Cipher.getInstance(ALGORITHM);  //根据指定算法ALGORITHM自成密码器
        cipher.init(Cipher.ENCRYPT_MODE, skey); //初始化密码器,第一个参数为加密(ENCRYPT_MODE)或者解密(DECRYPT_MODE)操作,第二个参数为生成的AES密钥
        byte [] encode_content = cipher.doFinal(content); //密码器加密数据
        return Base64.encodeBase64String(encode_content);
    }

    private static byte[] dnCode(String key,String content){    //content是base64编码字符串
        if (key == null || "".equals(key)) {
            return null;
        }
        if (key.length() != 16) {
            return null;
        }
        try {
            byte [] encode_content = Base64.decodeBase64(content); //把密文字符串转回密文字节数组
            byte[] raw = key.getBytes();  //获得密码的字节数组
            SecretKeySpec skey = new SecretKeySpec(raw, "AES"); //根据密码生成AES密钥
            Cipher cipher = Cipher.getInstance(ALGORITHM);  //根据指定算法ALGORITH生成密码器
            cipher.init(Cipher.DECRYPT_MODE, skey); //初始化密码器,第一个参数为加密(ENCRYPT_MODE)或者解密(DECRYPT_MODE)操作,第二个参数为生成的AES密钥
            return cipher.doFinal(encode_content); //将解密后的数据转换为字符串返回
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

测试

html:
<!DOCTYPE HTML>
<html>
<head><title>OutPutStream</title></head>
<body>

<label>
  输入要加密的文本:
  <input id="fs" name="ss" type="text" [(ngModel)]="data" (ngModelChange)="enTest()">
  <button style="background-color: yellow;" (click)="enTest()">加密</button>
  <button style="background-color: yellow;" (click)="deTest()">解密</button>
  <br>
  加密后的文本:<input type="text" [(ngModel)]="enData" disabled>
  <br>
  解密后的文本:<input type="text" [(ngModel)]="unData" disabled>
  <br><br>
  选择要加密的文件:
  <form style=" background-color: olivedrab" [formGroup]="myForm">
    <input  formControlName="EDI" type="file" class="form-control" (change)="handleFileSelect($event)">
  </form>
  <button style="background-color: yellow;" (click)="enFile()">加密文件</button>
  <button style="background-color: yellow;" (click)="deFile()">解密文件</button><br>

  加密后的文件: <input type="text" [(ngModel)]="enFileDataBase64" disabled>
  <br>
  <label>解密后的文件: </label><button style="background-color: yellow;" (click)="downLoadFile()">下载</button>
</label>
<!--<input type="file" id="fileUpload" value="选择文件" mce_style="display:none" οnchange="angular.element(this).scope().fileChoose(this)" >-->
<!--<button (click)="chaunshu()" class="btn btn-default">转移</button>-->
</body>
</html>
ts:
import {Component, OnInit} from '@angular/core';
import FileSaver from 'file-saver';
import {Buffer} from 'buffer';
import {AESUtils} from '../base/AESUtils';
import {AES, enc, lib, mode, pad} from 'crypto-js';

@Component({
  selector: 'testAES',
  templateUrl: './testAES.html',
  styleUrls: ['./testAES.css']
})

export class TestAES implements OnInit {
  myForm: any;
  scope: any;
  
  constructor() {
  }
  
  enData: any;
  data: string = '';
  unData: any;

  enFileData: any;
  enFileDataBase64: any;
  unFileData: any;
  key: string = "abcdefgabcdefg12";
  JsonObj: any;
  fileName: string;

  ngOnInit(): void {
  }

  handleFileSelect(evt) {
    const files = evt.target.files;
    const f = files[0];
    const reader = new FileReader();
    reader.readAsArrayBuffer(f);
    reader.onload = (f => {
      this.fileName = f.name;     //这是获取文件名,目的是获取文件的后缀
      return e => {
        this.JsonObj = e.target.result;     //文件的数据流
      };
    })(f);
  }

  public encrypt1(buf?: Buffer,key?:string): Buffer {
    let buffer = new Buffer([98, 99,-22,-44]);
    console.log(buffer.toString('base64'));
    let key16 = enc.Utf8.parse(this.key);          //将key转成16进制,如果不转解密也不能转并且加密后的数组动态的(如果有,解密必须有)
    var options = {
      mode: mode.ECB,     //模式
      padding: pad.Pkcs7  //补码方式
    };
    var encryptedData = AES.encrypt(lib.WordArray.create(buffer), key16, options);  //加密
    let buffer1 = new Buffer(encryptedData.toString(), 'base64');
    console.log(buffer1);
    console.log(encryptedData.toString());
    return   //解密后是base64的字符串,转为buff(字节数组)返回
  }

  public decrypt1(buf?: Buffer,key?:string): Buffer {
    let aaa = "TsA8sxb3ftE9s850oyueSQ==";
    let buffer1 = new Buffer([-22]);
    let s = buffer1.toString('base64');
    let key16 = enc.Utf8.parse(this.key);
    var options = {
      mode: mode.ECB,     //模式
      padding: pad.Pkcs7  //补码方式
    };
    let cipherParams = lib.CipherParams.create(buffer1);
    var decryptedData = AES.decrypt(s, key16, options);  //解密
    let buffer = new Buffer(enc.Base64.stringify(decryptedData),'base64');

    console.log(decryptedData.words);
    console.log(buffer);
    console.log(buffer.toString('base64'));
       //返回字节数组
  }

  enTest() {
    let a = AESUtils.encrypt(new Buffer([2,7,234,97]),this.key);
    console.log(a.toString("base64"));
  }
  deTest() {
    let a = AESUtils.decrypt(new Buffer("KJncoeWOUvKEQlfcE6KQLQ==",'base64'),this.key);
    console.log(a);
  }

  enFile() {
    this.enFileData = AESUtils.encrypt(this.JsonObj, this.key);     //加密
    this.enFileDataBase64 = this.enFileData.toString('base64'); //获取到加密后的base64字符
  }

  deFile() {
    this.unFileData = AESUtils.decrypt(this.enFileData,this.key); // 解密,解密出来的是buffer
  }

  downLoadFile() {
    const blob = new Blob([this.unFileData], {type: 'F:\\my-app\\src\\app\\;charset=utf-8'});
    FileSaver.saveAs(blob, this.fileName);
  }
}

3、jsencrypt实现rsa

RSAUtils

import {Buffer} from 'buffer';
import {JSEncrypt} from 'jsencrypt/lib';

declare var RSAUtil: any;

export class RSAUtils {
 private static jsEncrypt: JSEncrypt = new JSEncrypt({});

 /**
  * @param buf 字节数组
  * @param key key
  *
  * 传入字节数组和key,返回加密后的字节数组
  */
 public static getRSAKeys() {
   let publicKey = this.jsEncrypt.getKey().getPublicBaseKeyB64();
   let privateKey = this.jsEncrypt.getKey().getPrivateBaseKeyB64();
   return {publicKey, privateKey};
 }

 //传入Buffer,返回Buffer
 public static encodeRSA(buf: Buffer, publicKey: string): Buffer {
   let str = buf.toString('base64');     //将传入的buf转为base64(加一层base64,因为这个方法只能传String)
   this.jsEncrypt.setPublicKey(publicKey);
   let encrypt = this.jsEncrypt.encrypt(str);
   return new Buffer(encrypt, 'base64');
 }

 //传入Buffer,返回Buffer
 public static decodeRSA(buf: Buffer, privateKey: string): Buffer {
   let str = buf.toString('base64');   //将需要解密的Buffer转为base64字符串再解密
   this.jsEncrypt.setPrivateKey(privateKey);
   let decrypt = this.jsEncrypt.decrypt(str);
   return new Buffer(decrypt, 'base64'); //解密后转为Buffer(这里解的是最开始套的base64,因为底层加密只能用字符串)
 }

}

JAVA:

    public static String encrypt(String str, String publicKey) throws Exception{//key是16位str
        //base64编码的公钥
        byte[] decoded = Base64.decodeBase64(publicKey);
        RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
        //RSA加密
        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{
        //64位解码加密后的字符串
        byte[] inputByte = Base64.decodeBase64(str.getBytes(StandardCharsets.UTF_8));
        //base64编码的私钥
        byte[] decoded = Base64.decodeBase64(privateKey);
        RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
        //RSA解密
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, priKey);
        return new String(cipher.doFinal(inputByte));
    }

测试

输入要加密的文本:
<input id="fs1" name="ss" type="text" [(ngModel)]="data" (ngModelChange)="encrypt()">
<button style="background-color: yellow;" (click)="encrypt()">加密</button>
<button style="background-color: yellow;" (click)="decrypt()">解密</button><br>
加密的后的文本:<input id="fs2" name="ss" type="text" [(ngModel)]="enData"><br>
解密的后的文本:<input id="fs3" name="ss" type="text" [(ngModel)]="unData">
import {Component, OnInit} from '@angular/core';
import {Buffer} from 'buffer';
import {RSAUtils} from '../base/RSAUtils';
import FileSaver from 'file-saver';

@Component({
  selector: 'app-rsa',
  templateUrl: './rsa.html',
  styleUrls: ['./rsa.css']
})
export class Rsa implements OnInit{
  enData: any;
  data: string = '';
  unData: any;
  PRIVATE_KEY_CODE = "";
  PUBLIC_KEY_CODE = "";
  enFileDataBase64: any;
  enFileData: any;
  fileName: string;
  JsonObj: any;
  unFileData: any;

  constructor() { }
  ngOnInit(): void {
    this.getKeys();
  }

  getKeys(){
    let rsaKeys = RSAUtils.getRSAKeys();
    this.PUBLIC_KEY_CODE = rsaKeys.publicKey;
    this.PRIVATE_KEY_CODE = rsaKeys.privateKey;
  }

  encrypt(){
    let buffer = new Buffer(this.data);
    let buf = RSAUtils.encodeRSA(buffer,this.PUBLIC_KEY_CODE);
    let s = buf.toString('base64');
    // console.log(strB64);
    this.enData = s;
  }

  decrypt(){
    this.unData = RSAUtils.decodeRSA(this.enData,this.PRIVATE_KEY_CODE);
    console.log(this.unData);
  }
}
Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐