首页 > 解决方案 > 如何使用 Tink 轻松加密和解密字符串?

问题描述

到目前为止,我一直在使用 jasypt 加密字符串,然后在应用程序关闭时将其存储在磁盘上,然后在打开应用程序以在从磁盘检索字符串后解密字符串时。

使用 jasypt 非常简单,代码如下:

private static final String JASYPT_PWD = "mypassword";

public static String encryptString(String string) {
    StrongTextEncryptor textEncryptor = new StrongTextEncryptor();
    textEncryptor.setPassword(JASYPT_PWD);
    return textEncryptor.encrypt(string);
}

public static String decryptString(String string) {
    StrongTextEncryptor textEncryptor = new StrongTextEncryptor();
    textEncryptor.setPassword(JASYPT_PWD);
    return textEncryptor.decrypt(string);
}

它工作得很好,但是现在,jasypt 已被弃用,我正在尝试迁移到Google Tink库,问题是 Google Tink 似乎要复杂得多,因为只需像使用 jasypt 一样轻松地加密和解密字符串。

我在 Tink repo 自述文件中找不到加密和解密字符串的简单方法,只能找到更复杂的操作,实际上我无法理解,因为我在加密方面的知识完全是空的。因此,我使用了一个非常简单的库,比如 jasypt。

这是 Tink 仓库:https ://github.com/Google/tink

有没有一种简单的方法,类似于我的 jasypt 代码,用 Tink 加密和解密字符串?

标签: javaencryptionjasyptkeyczartink

解决方案


注意:帖子指的是Tink 版本 1.2.2。发布的代码与更高版本部分不兼容。

-example-code中的StrongTextEncryptor-class使用-algorithm。该算法使用对称密钥分组密码,并使用散列函数从密码中导出密钥。后者称为基于密码的加密,并且不支持(至少在 08/2018 时),请参阅如何使用 Google Tink 创建对称加密密钥?. 因此,不可能通过密码进行加密,并且迄今为止在-code中使用的概念无法实现。如果要在任何情况下使用基于密码的加密,这对.jasyptPBEWithMD5AndTripleDESTriple DESMD5TinkTinkjasyptTink

另一种方法是直接使用密钥。Tink具有用于加密的AesGcmJce-class 。AES-GCM此处密钥的长度必须为 128 位或 256 位:

String plainText = "This is a plain text which needs to be encrypted!";
String aad = "These are additional authenticated data (optional)";
String key = "ThisIsThe32ByteKeyForEncryption!"; // 256 bit
    
// Encryption
AesGcmJce agjEncryption = new AesGcmJce(key.getBytes());
byte[] encrypted = agjEncryption.encrypt(plainText.getBytes(), aad.getBytes());

// Decryption
AesGcmJce agjDecryption = new AesGcmJce(key.getBytes());
byte[] decrypted = agjDecryption.decrypt(encrypted, aad.getBytes());

使用简单,而且使用的密码 ( AES-GCM) 是安全的。但是,Tink-developers 自己不推荐这种方法,因为AesGcmJce-class 属于com.google.crypto.tink.subtle-package可能随时更改,恕不另行通知,(另请参见此处重要警告部分)。因此,这种方法也不是最优的。

那么,Tink通常如何使用对称加密呢?这显示在以下片段

String plainText = "This is a plain text which needs to be encrypted!";
String aad = "These are additional authenticated data (optional)";

AeadConfig.register();
    
KeysetHandle keysetHandle = KeysetHandle.generateNew(AeadKeyTemplates.AES256_GCM);
Aead aead = AeadFactory.getPrimitive(keysetHandle);
    
// Encryption
byte[] ciphertext = aead.encrypt(plainText.getBytes(), aad.getBytes());

// Decryption
byte[] decrypted = aead.decrypt(ciphertext, aad.getBytes());

-generateNew方法生成一个密钥。但是,创建不是基于密码或字节序列,因此,为加密生成的密钥无法轻松重建以进行解密。因此,用于加密的密钥必须保存在存储系统中,例如文件系统,以便以后用于解密。Tink允许存储明文密钥(当然不推荐)。一种更安全的方法是使用存储在远程密钥管理系统中的主密钥对密钥进行加密(这在JAVA-HOWTOTink存储密钥集和加载现有密钥集部分有更详细的解释)。

Tink的密钥管理概念(旨在避免敏感密钥材料的意外泄漏)使其在某种程度上也很麻烦(这可能会在以后的版本中改变)。这就是为什么我在评论中说我不确定是否Tink符合您关于简单性的想法。


推荐阅读