java - 安全传输 SecretKey 以对密码进行加密/解密
问题描述
我正在考虑使用 ChaCha20-Poly1305 加密/解密密码(我需要加密/解密不能只散列)。但是,要使用此算法,我们需要使用密钥。但是,这是一个问题,因为我在他们的设备上加密/解密用户的密码,所以在我的数据库中我只存储他们的加密密码。
问题在于,如果用户从他们的手机中卸载我的应用程序或更换为新手机,我将需要相同的密钥才能再次解密用户的密码。
我的问题是:我如何安全地传输和存储这个密钥?
另外,如果您对我的问题有更好的替代方案,例如不同的加密算法或方法,请告诉我。
这是我提到的 SecretKey 对象的代码示例:
package com.javainterviewpoint;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class ChaCha20Poly1305Example
{
static String plainText = "This is a plain text which will be encrypted by ChaCha20 Poly1305 Algorithm";
public static void main(String[] args) throws Exception
{
KeyGenerator keyGenerator = KeyGenerator.getInstance("ChaCha20");
keyGenerator.init(256);
// Generate Key
SecretKey key = keyGenerator.generateKey();
System.out.println("Original Text : " + plainText);
byte[] cipherText = encrypt(plainText.getBytes(), key);
System.out.println("Encrypted Text : " + Base64.getEncoder().encodeToString(cipherText));
String decryptedText = decrypt(cipherText, key);
System.out.println("DeCrypted Text : " + decryptedText);
}
public static byte[] encrypt(byte[] plaintext, SecretKey key) throws Exception
{
byte[] nonceBytes = new byte[12];
// Get Cipher Instance
Cipher cipher = Cipher.getInstance("ChaCha20-Poly1305/None/NoPadding");
// Create IvParamterSpec
AlgorithmParameterSpec ivParameterSpec = new IvParameterSpec(nonceBytes);
// Create SecretKeySpec
SecretKeySpec keySpec = new SecretKeySpec(key.getEncoded(), "ChaCha20");
// Initialize Cipher for ENCRYPT_MODE
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivParameterSpec);
// Perform Encryption
byte[] cipherText = cipher.doFinal(plaintext);
return cipherText;
}
public static String decrypt(byte[] cipherText, SecretKey key) throws Exception
{
byte[] nonceBytes = new byte[12];
// Get Cipher Instance
Cipher cipher = Cipher.getInstance("ChaCha20-Poly1305/None/NoPadding");
// Create IvParamterSpec
AlgorithmParameterSpec ivParameterSpec = new IvParameterSpec(nonceBytes);
// Create SecretKeySpec
SecretKeySpec keySpec = new SecretKeySpec(key.getEncoded(), "ChaCha20");
// Initialize Cipher for DECRYPT_MODE
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivParameterSpec);
// Perform Decryption
byte[] decryptedText = cipher.doFinal(cipherText);
return new String(decryptedText);
}
}
解决方案
对于对称加密和解密,最佳实践是使用一个 MASTER KEY,它是固定字符串或具有固定算法,您知道如何生成它。您必须使用此 MASTER KEY 来加密和解密所有其他密钥(名称 WORKING KEYS)来加密/解密真实数据。
如果您的设备有一个安全区域,您可以安全地保存您的密钥,您必须通过另一台设备或通过与服务器通信在其上注入主密钥。如果没有,您将面临泄露密钥的风险。
但是,如果您是应用程序的唯一程序员,您可以使用固定算法生成 MASTER 密钥。例如使用设备hash(xor(
的1c1c1c
ID。现在,设备可以向服务器发送获取工作密钥的请求(通过发送其 id 和由主密钥加密的 mac-block),然后您返回正确的工作密钥。
此方案在 ISO-8583 支付中使用。
推荐阅读
- r - 根据动态值集分配固定的 ggplot2 形状
- rabbitmq - 从 RabbitMQ 消息中确定原始交换
- r - Frequency table base R vs renderTable Shiny
- android - 上下文 - 空对象引用
- node.js - 在 bcrypt 中比较两个相同的字符串散列返回未定义
- javascript - AngularJS http post and delete data
- c# - sending checkbox value true if checked else false with form object using jQuery in mvc
- google-places-api - Google Places API 请求的会话令牌参数的正确拼写是什么?
- dns - 为什么 Kubernetes 上没有开箱即用地启用 dns 本地缓存?
- sql - A table with several columns in addition to a date/time column. How to query and avoid duplicate dates stamps?