0

我正在尝试在 python3 中实现对 pushbullet 临时消息的端到端加密支持。

我正在使用python-cryptography,但InvalidTag解密时出现 -Exception 。我已经仔细检查了密钥、iv 和标签,但我不知道哪里出了问题。

密钥是这样派生的:

    salt = user_ident.encode()
    pw = password.encode()

    kdf = PBKDF2HMAC(
            algorithm=hashes.SHA256(), 
            length=32,
            salt=salt,
            iterations=30000,
            backend=backend)

    dkey = kdf.derive(pw)

然后将其作为 Base64 编码字符串存储在密钥环中,但我仔细检查了加密时是否获得了正确的字节字符串(也可以在 REPL 中手动执行)。

解密:

ciphertxt = a2b_base64(msg['ciphertext'])
version = ciphertxt[0:1]
tag = ciphertxt[1:17]
iv = ciphertxt[17:29]
enc_msg = ciphertxt[29:]

# Construct an AES-GCM Cipher object
decryptor = Cipher(
    algorithms.AES(self.dkey_),
    modes.GCM(iv, tag),
    backend=backend
).decryptor()

cleartxt = decryptor.update(enc_msg) + decryptor.finalize()

所有变量都是字节字符串,这里是 python-cryptography 的相关文档

澄清一下:我已经尝试过自己的方法来加密和成功解密一些文本。但是,当我在手机和客户端上激活 Pushbullet e2e 加密并收到通知时,我收到上述错误。

加密方法像这样组装加密的消息:

b'1' + encryptor.tag + iv + ciphertxt

我可以破译它。不适用于收到消息中的标签。

有任何想法吗?:/

4

1 回答 1

0

我最近在文档页面上添加了一些交互式 javascript 内容:https ://docs.pushbullet.com/#example-encrypt-a-message

我发现调试此类问题的最佳方法是单独测试每个部分,并确保您获得给定输入的正确输出。

在您的情况下,我认为您应该创建一个不会更改的密钥、IV 和消息,并确保您的库生成与该示例中的 javascript 代码相同的 encrypted_message。以下是它的外观:

// convert key from base64 to binary
var key = atob("1sW28zp7CWv5TtGjlQpDHHG4Cbr9v36fG5o4f74LsKg=");
var initialization_vector = atob("O2QAL8AYQB+qbre8"); // 96-bit
var message = "meow!";

var cipher = forge.cipher.createCipher('AES-GCM', key);
cipher.start({"iv": initialization_vector});
cipher.update(forge.util.createBuffer(forge.util.encodeUtf8(message)));
cipher.finish();

var tag = cipher.mode.tag.getBytes();
console.log("tag", btoa(tag));
var encrypted_message = cipher.output.getBytes();
console.log("encrypted_message", btoa(encrypted_message));

输出是:

tag OBA7UU/Rd9j0Zn+9korAyQ== 
encrypted_message 7YS1aTE= 

一旦您的 python 加密与此匹配,您应该确保解密部分有效。

var key = atob("1sW28zp7CWv5TtGjlQpDHHG4Cbr9v36fG5o4f74LsKg=")
var tag = atob("OBA7UU/Rd9j0Zn+9korAyQ==")
var initialization_vector = atob("O2QAL8AYQB+qbre8"); // 96 bits
var encrypted_message = atob("7YS1aTE=");

var decipher = forge.cipher.createDecipher('AES-GCM', key);
decipher.start({
    'iv': initialization_vector,
    'tag': tag
});
decipher.update(forge.util.createBuffer(encrypted_message));
decipher.finish();

var message = decipher.output.toString('utf8');
console.log("message:", message);

哪个应该打印:

message: meow! 

我对那个特定的 python 库没有任何经验,但如果你使用这种调试技术,你应该能够缩小问题所在。

于 2015-08-27T21:26:44.230 回答