我正在开发 Java 应用程序来创建数字签名来签署文档。我已经使用(椭圆曲线密码学)ECC 创建了私钥和公钥,现在我想将这两个密钥都存储在 mysql 数据库中。
我对公钥没有任何问题,但我关心的是安全地存储私钥。
我正在使用 AES 128 位加密来自用户的私钥和 6 位密码以存储在数据库中。要加密它,我还需要生成盐和初始化向量。
但是现在,要解密它,我还需要知道我用来解密加密私钥的相同盐和初始化向量 (iv)。
问题一:
使用私钥将盐和向量存储在数据库同一张表中是否安全?目前我对公钥和私钥、salt 和 iv 进行编码,并在数据库中保存为字符串(数据类型 VARCHAR)。
问题2:
以下是我设计的当前工作流程。这是最佳做法吗?我不想做太多会影响 CPU 使用率的进程。
创建密钥
- 使用 ECC 创建私钥
- 编码私钥(字节到字符串)
- 使用 AES 加密私钥
- 编码私钥,盐,iv(字节到字符串)
- 作为 VARHCAR 存储在数据库中
签署文件
- 从数据库中检索私钥
- 解码私钥、盐、iv
- 解密私钥
- 解码私钥
- 将解码的密钥转换为实际的私钥以进行签名
生成密钥和加密的代码片段:
//Generate salt
Random r = new SecureRandom();
byte[] salt = new byte[8];
r.nextBytes(salt);
//System.out.println("salt: "+salt);
//initialize vector
byte[] vector = new byte[128/8];
r.nextBytes(vector);
IvParameterSpec ivspec = new IvParameterSpec(vector);
//System.out.println("iv: "+iv);
//initialize variables
String MsgToEncrypt = encodedECCprivateKeyBytes;
String userPin = ParamUtil.getString(actionRequest, "userPin");
Cipher ecipher;
//Generating AES key
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec mykeySpec = new PBEKeySpec(userPin.toCharArray(), salt, 10000, 128);
SecretKey tmp = factory.generateSecret(mykeySpec);
SecretKeySpec mySecretkey = new SecretKeySpec(tmp.getEncoded(), "AES");
//==> Create and initiate encryption
System.out.println("Initiate encryption alogrithm...");
ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
//System.out.println("Algorithm to encrypt private key: " + ecipher);
ecipher.init(Cipher.ENCRYPT_MODE, mySecretkey, ivspec);
//System.out.println("SecKey: "+mySecretkey);