到目前为止,我一直使用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库,问题在于,与像jasypt一样,仅加密和解密字符串,Google Tink似乎要复杂得多。

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

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

有没有一种类似于我的Jasypt代码的简便方法,可以使用Tink加密和解密字符串?

最佳答案

StrongTextEncryptor -example-code中的 jasypt -class使用PBEWithMD5AndTripleDES -algorithm。该算法使用对称密钥块密码Triple DES,并使用MD5哈希函数从密码中得出密钥。后者称为基于密码的加密,并且Tink不支持此功能(至少在08/2018起),请参阅How to create symmetric encryption key with Google Tink?。因此,在Tink中不可能通过密码进行加密,并且到目前为止在jasypt -code中使用的概念都无法实现。如果在任何情况下都使用基于密码的加密,那么Tink会破坏交易。

另一种方法是直接使用密钥。 Tink具有 AesGcmJce -类,该类使用 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-开发人员自己不推荐这种方法,因为AesGcmJce -class属于com.google.crypto.tink.subtle -package which may change at any time without further notice(另请参见here,重要警告部分)。因此,这种方法也不是最优的。

那么,Tink通常如何使用对称加密?这在以下片段from中显示:
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 -method生成一个新密钥。但是,创建不是基于密码或字节序列的,因此,为加密而生成的密钥不能轻易地重构用于解密。因此,用于加密的密钥必须持久保存到存储系统中,例如文件系统,因此以后可以用于解密。 Tink允许存储明文密钥(当然不建议这样做)。一种更安全的方法是使用存储在远程密钥管理系统中的主密钥对密钥进行加密(这将在TinkJAVA-HOWTO的“存储密钥集和加载现有密钥集”部分中进行详细说明)。
Tink的密钥管理概念(旨在避免敏感密钥材料的意外泄漏)使其变得笨拙(在以后的版本中可能会改变)。这就是为什么我在评论中说,我不确定Tink是否符合您关于简单性的想法。

09-10 06:38