使用 python-cryptography 解密 pushbullet 通知时出现 InvalidTag 错误
InvalidTag error decrypting pushbullet notification with python-cryptography
我正在尝试为 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-密码学的relevant docs。
澄清一下:
我尝试了自己的方法来加密并成功解密一些文本。但是当我在我的 phone 和我的客户端上激活 Pushbullet e2e 加密并且我收到通知时,我得到了上面的错误。
加密方法像这样组装加密消息:
b'1' + encryptor.tag + iv + ciphertxt
而且我可以破译它。不适用于收到的邮件中的标签。
有什么想法吗? :/
我最近在文档页面上添加了一些交互式 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 库没有任何经验,但如果您使用这种调试技术,您应该能够缩小问题所在的范围。
我正在尝试为 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-密码学的relevant docs。
澄清一下: 我尝试了自己的方法来加密并成功解密一些文本。但是当我在我的 phone 和我的客户端上激活 Pushbullet e2e 加密并且我收到通知时,我得到了上面的错误。
加密方法像这样组装加密消息:
b'1' + encryptor.tag + iv + ciphertxt
而且我可以破译它。不适用于收到的邮件中的标签。
有什么想法吗? :/
我最近在文档页面上添加了一些交互式 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 库没有任何经验,但如果您使用这种调试技术,您应该能够缩小问题所在的范围。