如何使用 Tink 轻松加密和解密字符串?

Nul*_*ion 7 java encryption jasypt keyczar 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);
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

Top*_*aco 13

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

-example-code 中的StrongTextEncryptor-classjasypt使用PBEWithMD5AndTripleDES-algorithm。该算法使用对称密钥分组密码,Triple DES并使用MD5散列函数从密码中派生出密钥。后者被称为基于密码的加密,这是不支持Tink(至少截至08/2018),请参阅如何创建与谷歌亭对称加密密钥?. 因此,不可能Tink通过密码进行加密,并且到目前为止在jasypt-code 中使用的概念无法实现。如果在任何情况下都使用基于密码的加密,这对于Tink.

另一种方法是直接使用密钥。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());
Run Code Online (Sandbox Code Playgroud)

使用简单,而且使用的密码(AES-GCM)是安全的。但是,开发Tink人员自己不推荐这种方法,因为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());
Run Code Online (Sandbox Code Playgroud)

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

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

  • @Renis1235 - 该帖子是 2019 年 3 月发布的。发布的代码与当时的 Tink 版本(1.2.2)兼容。今天(2021 年 4 月)当前的 Tink 版本是 1.5.0,发布的代码不再兼容。我已将链接从主版本(当前版本 1.5)移至版本 1.2.2,以便引用 1.2.2 文档(像以前一样)并且链接再次与文本一致。 (2认同)

Tha*_*ong 5

免责声明:我是 Tink 的首席开发人员。

如果您正在开发 Android 应用程序,则可以查看AndroidKeysetManager. 有一个你可以复制的 hello world 示例

一般来说,无论何时你想加密一些东西,你应该问自己的第一个问题是你将在哪里存储密钥。将密钥存储在您存储加密数据的同一位置(并使用相同的 ACL)并没有多大意义。密钥应该存储在不同的位置(或使用不同的 ACL)。

Tink 的密钥管理 API 有点复杂,因为我们希望引导用户将密钥存储在正确的位置

  • 请您添加一种简单的方法来加密和解密字符串以用于像 jasypt 这样的简单用途吗?有时,不需要太多敏感数据需要加密,只是为了适合一个小而不复杂的必需品,在这种情况下,你的图书馆太复杂了 (2认同)