記事ディレクトリ
序文
このプロジェクトでは、プライベート パラメーターを暗号化する手順に遭遇したため、意図的に非対称暗号化と対称暗号化の 2 つの例を学習しました。
1. 対称暗号化と非対称暗号化とは何ですか?
1.1. 対称暗号化の概要
対称暗号化は最も高速かつ簡単な暗号化方法であり、暗号化と復号化に同じ秘密キーが使用されます。
対称暗号化では通常、比較的小さいキー (通常は 256 ビット未満) が使用されます。キーが大きいほど暗号化は強力になりますが、暗号化と復号化のプロセスは遅くなります。
対称暗号化の主な欠点は、キーの管理と配布、つまり、メッセージを復号化する必要がある人の手にキーをどのように送信するかという問題です。キーを送信する過程で、キーがハッカーによって傍受される大きなリスクがあります。実際には、対称暗号化キーを非対称的に暗号化し、それを必要とする人に送信するのが通常の方法です。
対称暗号化は暗号化速度が非常に速いため、頻繁にデータを送信する場合に適しています。欠点は、キーの送信が面倒で、一般的な AES であることです。
1.2. 非対称暗号化の概要
非対称暗号化は、公開キーと秘密キーのペアのキーを使用する、データの暗号化と復号化に非常に安全な方法を提供します。秘密キーは一方の当事者のみが安全に保管でき、漏洩することはありませんが、公開キーは要求した人に配布できます。非対称暗号化では、キーのペアの一方を使用して暗号化しますが、復号化にはもう一方のキーが必要です。つまり、公開キーで暗号化し、秘密キーで復号化します。
非対称アルゴリズムのため、暗号化と復号化の速度は比較的遅く、データが時々送信される場合に適しています。キー送信が便利なのがメリットです。一般的な非対称暗号化アルゴリズムは、RSA、ECC、EIGamal です。
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);
}
}