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

时间:2019-03-08 20:24:54

标签: 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);
}

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

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

这是Tink回购:https://github.com/Google/tink

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

3 个答案:

答案 0 :(得分:3)

您的jasypt示例代码中的StrongTextEncryptor类使用PBEWithMD5AndTripleDES算法。该算法使用对称密钥块密码Triple DES,并使用MD5哈希函数从密码中得出密钥。后者称为基于密码的加密Tink(至少截至08/2018)不支持该 ,请参见How to create symmetric encryption key with Google Tink? 。因此,在Tink中不可能通过密码进行加密,并且到目前为止在jasypt代码中使用的概念都无法实现。如果在任何情况下都要使用基于密码的加密,那么这对于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类属于com.google.crypto.tink.subtlewhich 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方法将生成一个 new 密钥。但是,创建不是基于密码或字节序列的,因此,为加密而生成的密钥不能轻易地重构用于解密。因此,用于加密的密钥必须持久保存到存储系统中,例如文件系统,因此以后可以用于解密。 Tink允许存储明文密钥(当然不建议这样做)。一种更安全的方法是使用存储在远程密钥管理系统中的主密钥对密钥进行加密(这在Tink的{​​{3}},存储密钥集加载现有键集)。

Tink的密钥管理概念(目的是避免敏感密钥材料的意外泄漏)使其变得笨拙(在以后的版本中可能会有所变化)。这就是为什么我在评论中说,我不确定Tink是否适合您关于简单性的想法。

答案 1 :(得分:0)

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

(我没有足够的声誉来发表评论,所以我要添加一个答案)

Peter,如果您使用的是Android应用程序,则可以签出AndroidKeysetManager [2]。有一个您可以复制的世界示例[3]。

通常,每当您要加密某些内容时,您首先要问自己的问题是要将密钥存储在何处。将密钥存储在存储加密数据的相同位置(和相同的ACL)并没有多大意义。密钥应存储在其他位置(或使用不同的ACL)。

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

[1] https://github.com/google/tink/blob/master/docs/JAVA-HOWTO.md#storing-keysets

[2] http://google.github.io/tink/javadoc/tink-android/1.2.2/com/google/crypto/tink/integration/android/AndroidKeysetManager.html

[3] https://github.com/google/tink/blob/master/examples/helloworld/android/app/src/main/java/com/helloworld/TinkApplication.java

答案 2 :(得分:0)

我一直在寻找一种简单的方法来使用基于密码的加密(PBE)对短消息进行加密,并将Google Tink用于加密部分,结果发现Tink本身并不提供PBE。为了解决这个问题,我制作了一个简单的类,可以完成PBE,密钥处理和加密/解密的所有工作。

程序中的用法非常简单,您只需要4行代码即可使用它:

let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewController(withIdentifier: "meniuControl4") as! SideMenuController
self.present(nextViewController, animated:true, completion:nil)

在我的Github上,您找到两个示例程序来展示如何实现该类(带有和不带有GUI):https://github.com/java-crypto/H-Google-Tink/tree/master/H%20Tink%20Textencryption%20PBE

这是TinkPbe.java类的源代码:

AeadConfig.register(); // tink initialisation
TinkPbe tpbe = new TinkPbe(); // tink pbe initialisation
String ciphertextString = tpbe.encrypt(passwordChar, plaintextString); // encryption
String decryptedtextString = tpbe.decrypt(passwordChar, ciphertextString); // decryption

请记住,使用纯文本-字符串意味着您的纯文本在您的堆中是不变且不可删除的,直到垃圾收集器将其销毁为止。

我的网站上提供了更详细的描述:http://javacrypto.bplaced.net/h-tink-string-encryption-using-pbe-and-gui/