実際のプロジェクトでのRSA非対称暗号化とAES対称暗号化の使用


序文

このプロジェクトでは、プライベート パラメーターを暗号化する手順に遭遇したため、意図的に非対称暗号化と対称暗号化の 2 つの例を学習しました。


1. 対称暗号化と非対称暗号化とは何ですか?

1.1. 対称暗号化の概要

対称暗号化は最も高速かつ簡単な暗号化方法であり、暗号化と復号化に同じ秘密キーが使用されます。

対称暗号化では通常、比較的小さいキー (通常は 256 ビット未満) が使用されます。キーが大きいほど暗号化は強力になりますが、暗号化と復号化のプロセスは遅くなります。

対称暗号化の主な欠点は、キーの管理と配布、つまり、メッセージを復号化する必要がある人の手にキーをどのように送信するかという問題です。キーを送信する過程で、キーがハッカーによって傍受される大きなリスクがあります。実際には、対称暗号化キーを非対称的に暗号化し、それを必要とする人に送信するのが通常の方法です。

対称暗号化は暗号化速度が非常に速いため、頻繁にデータを送信する場合に適しています。欠点は、キーの送信が面倒で、一般的な AES であることです。

1.2. 非対称暗号化の概要

非対称暗号化は、公開キーと秘密キーのペアのキーを使用する、データの暗号化と復号化に非常に安全な方法を提供します。秘密キーは一方の当事者のみが安全に保管でき、漏洩することはありませんが、公開キーは要求した人に配布できます。非対称暗号化では、キーのペアの一方を使用して暗号化しますが、復号化にはもう一方のキーが必要です。つまり、公開キーで暗号化し、秘密キーで復号化します。
  
非対称アルゴリズムのため、暗号化と復号化の速度は比較的遅く、データが時々送信される場合に適しています。キー送信が便利なのがメリットです。一般的な非対称暗号化アルゴリズムは、RSA、ECC、EIGamal です。

AES暗号化原理
RAS暗号化原理

2. RSA 非対称暗号化のフロントエンドおよびバックエンドの実装

2.1、フロントエンドは rsa を実装します

1. jsencryptをインストールし、次のコマンドを実行します。

npm install jsencrypt --save-dev

2. encryptlong をインストールするには、次のコマンドを実行します。

npm i encryptlong -S

3. 公開鍵と秘密鍵の生成
publicKey (公開鍵) と privateKey (秘密鍵) を準備して、
オンラインで公開鍵と秘密鍵の URL を生成します

4. フロントエンドコードの実装

/* 产引入jsencrypt实现数据RSA加密 */
import JSEncrypt from 'jsencrypt' // 处理长文本数据时报错 jsencrypt.js Message too long for RSA
/* 产引入encryptlong实现数据RSA加密 */
import Encrypt from 'encryptlong' // encryptlong是基于jsencrypt扩展的长文本分段加解密功能。
 
// 密钥对生成 http://web.chacuo.net/netrsakeypair
 
// 公钥key
const publicKey = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANL378k3RiZHWx5AfJqdH9xRNBmD9wGD\n' +
  '2iRe41HdTNF8RUhNnHit5NpMNtGL0NPTSSpPjjI1kJfVorRvaQerUgkCAwEAAQ=='
// 私钥key
const privateKey = 'MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8\n' +
  'mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9p\n' +
  'B6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue\n' +
  '/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZ\n' +
  'UBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6\n' +
  'vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha\n' +
  '4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3\n' +
  'tTbklZkD2A=='
 
export default {
    
    
  /* JSEncrypt加密 */
  rsaPublicData(data) {
    
    
    var jsencrypt = new JSEncrypt()
    jsencrypt.setPublicKey(publicKey)
    // 如果是对象/数组的话,需要先JSON.stringify转换成字符串
    var result = jsencrypt.encrypt(data)
    return result
  },
  /* JSEncrypt解密 */
  rsaPrivateData(data) {
    
    
    var jsencrypt = new JSEncrypt()
    jsencrypt.setPrivateKey(privateKey)
    // 如果是对象/数组的话,需要先JSON.stringify转换成字符串
    var result = jsencrypt.encrypt(data)
    return result
  },
  /* 加密 */
  encrypt(data) {
    
    
    const PUBLIC_KEY = publicKey
    var encryptor = new Encrypt()
    encryptor.setPublicKey(PUBLIC_KEY)
    // 如果是对象/数组的话,需要先JSON.stringify转换成字符串
    const result = encryptor.encryptLong(data)
    return result
  },
  /* 解密 - PRIVATE_KEY - 验证 */
  decrypt(data) {
    
    
    const PRIVATE_KEY = privateKey
    var encryptor = new Encrypt()
    encryptor.setPrivateKey(PRIVATE_KEY)
    // 如果是对象/数组的话,需要先JSON.stringify转换成字符串
    var result = encryptor.decryptLong(data)
    return result
  }
}

4. グローバル参照

import Rsa from "@/utils/rsa.js"
Vue.prototype.Rsa = Rsa //

5. RSA を使用して *.vue ページにソリューションを追加し、グローバルに使用します

this.Rsa.方法名 

リファレンスフロントエンド実装

2.2、バックエンドは RSA 復号化を実装します

1. hutool 依存関係を導入する



<!-- 工具类 参考https://hutool.cn/docs-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.3.10</version>
        </dependency>

2.方法

private String decodeStr(String encodeStr) {
    
    
        try {
    
    
            String privateKey = ResourceUtil.readUtf8Str(PRIVATE_KEY_LOCATION);
            RSA rsa = new RSA(privateKey, null);
            byte[] aByte = SecureUtil.decode(encodeStr);
            byte[] decrypt = rsa.decrypt(aByte, KeyType.PrivateKey);
            return StrUtil.str(decrypt, CharsetUtil.CHARSET_UTF_8);
        } catch (Exception e) {
    
    
            logger.error("RSA私钥解密失败!", e);
            throw new BadCredentialsException(encodeStr);
        }
    }

3. hutool の暗号化と復号化の使用については、
hutools アドレスを参照してください。
ここに画像の説明を挿入

3. AES暗号化のフロントエンドおよびバックエンドの実装

3.1、AES フロントエンドの実装

1. 依存関係をダウンロードする

 下载crypto-js
npm install crypto-js --save

2. コードの具体的な使用方法

import CryptoJS from 'crypto-js'

const key = 'f4k9f5w7f8g4er26' //前后端使用同意秘钥
// 偏移量 16位(不可随意修改,否则前后端加密解密可能失败)
const iv = '0000000000000000'

export function encrypt(data) {
    
    
  return CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(data), CryptoJS.enc.Utf8.parse(key), {
    
    
    iv: CryptoJS.enc.Utf8.parse(iv),
    mode: CryptoJS.mode.ECB,
    padding: CryptoJS.pad.Pkcs7
  })
    .toString()
}
export function decrypt(data) {
    
    
  const decrypted = CryptoJS.AES.decrypt(data, CryptoJS.enc.Utf8.parse(key), {
    
    
    mode: CryptoJS.mode.ECB,
    padding: CryptoJS.pad.Pkcs7
  })
  return decrypted.toString(CryptoJS.enc.Utf8).toString()
}

3. グローバル参照は上記の rsa と同じです。

3.2. AES バックエンド復号化の実装 (2 つの方法)

1. hutool ツールを使用します (hutool を使用すると比較的便利です)
ここに画像の説明を挿入

String content = "test中文";

//随机生成密钥
byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.AES.getValue()).getEncoded();

//构建
SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, key);

//加密
byte[] encrypt = aes.encrypt(content);
//解密
byte[] decrypt = aes.decrypt(encrypt);

//加密为16进制表示
String encryptHex = aes.encryptHex(content);
//解密为字符串
String decryptStr = aes.decryptStr(encryptHex, CharsetUtil.CHARSET_UTF_8);

2. コモンズコードに依存するツールを使用して
依存関係を導入する

<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.15</version>
</dependency>

AESツール

public class Encrypt {
    
    

    //--------------AES---------------
    private static final String KEY = "f4k9f5w7f8g4er26";  // 密匙,必须16位
    private static final String ENCODING = "UTF-8"; // 编码
    private static final String ALGORITHM = "AES"; //算法
    private static final String CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding"; // 默认的加密算法,ECB模式

    /**
     *  AES加密
     * @param data
     * @return String
     */
    public static String AESencrypt(String data) throws Exception
    {
    
    
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128);
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE,new SecretKeySpec(KEY.getBytes(),"AES"));
        byte[] b = cipher.doFinal(data.getBytes("utf-8"));
        //采用base64算法进行转码,避免出现中文乱码
        return Base64.encodeBase64String(b);
    }

    /**
     * AES解密
     * @param data
     * @return String
     */
    public static String AESdecrypt(String data) throws Exception {
    
    
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128);
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(KEY.getBytes(), "AES"));
        byte[] b = cipher.doFinal(Base64.decodeBase64(data));
        //采用base64算法进行转码,避免出现中文乱码
        return new String(b);
    }
    public static void main(String[] args) throws Exception {
    
    
        String mi = Encrypt.AESencrypt("111111");
        System.out.println(mi);
    }

}

おすすめ

転載: blog.csdn.net/wei1359765074410/article/details/127786653