我正在开发 WhatsApp Flows API,并决定接受 Go 中的挑战。
部分实现要求我使用 AES-256 加密来加密响应,并且我已经设法让它在 Python 中工作。问题是当我尝试在 Go 中做同样的事情时,我得到了不同的结果。有人可以帮我在 go 中复制以下代码、输入和输出吗:
encrypted_flow_data_b64 = 'H78/q8TCjizJhK8yt8tPEHG2QzArPsEFIoLajXWuPb5s6RA0QfHE7JMFFw3hTNh1byNSwjGVic8r2V9j76q4Et8UM9/bMCsF3UnXEzPNTZgQH4FHUIyjNQ=='
encrypted_aes_key_b64 = 'rjbs78LfWHLLqay/Fe4ofEisbMhCINmdUMlwXREuBGfRVRQzDmfEMoMFdCwLaX66nh/x7lJDyyjQZ+XA50gN1hEuDji0qbyGgpzZUUUfkxqYsgDW61Nf93cWvCPIRsgfuP5Brggoqr3slfRLbLPUOjkYOaof7lGJqHHbBeIb4RgEOAaIOXCA+84W5wrU/hmODoGNQ5FV7zjRdOpd8vX6JXcQ46LCLtmfPr0zx0NVetP8qvM7sn2X7FXlZtebut3k4XWkWQd3GEyWw5MEm4a4TJGtrXBAqcl7jsbTExgfVnVFD6saRKCoy2m6FqouMw9CzU5KyNItWhXkE4HtzKQilA=='
initial_vector_b64 = 'S84bbuqcCYjCtLECg9sq+A=='
import json
import os
import base64
from base64 import b64decode, b64encode
from cryptography.hazmat.primitives.asymmetric.padding import OAEP, MGF1, hashes
from cryptography.hazmat.primitives.ciphers import algorithms, Cipher, modes
from cryptography.hazmat.primitives.serialization import load_pem_private_key
from cryptography.hazmat.backends import default_backend
PRIVATE_KEY = b"""-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC7vQZb2hKIDIow
jq7Vcwvq3/24kJpES26WUhcMXchqghgjAHP4X/2WMP37Qf+m4qahl91ZVyC8lQ1m
edSOJWoFj62I8ShI32EEQHFwhEIQKP/Q/6DY4xy7psetLcxZErcB5XJuxK6vni/j
EkJcGxmAYOHeatqY/Ij4TOPlrRJjMNgTsSxdgu5o+ulQAm7n/iBavbCwLkusog/8
6GG7V+2EQ143mKHTdAeohTcn/PR9W7l6kq7ChYIkXQbc/pG1Jq7dqsW1IQGBCxNT
SwOCOFq6nQgtV+x4gowIF3OJ7Ae6KNPKbVCec78LtiTM9pxPoWzvov3+3JsGAB3U
zBiZdHD1AgMBAAECggEAAJz/C2eZ4Lq6bIBZfFuDmgkQx7H7Owa3DgPRzPR1I49D
Zmve38cVKZDakjVL5pQ+IJrXJNlRbfmbrAPGXg+BD5MW/p1GY9SM+Sn/ujMdvHac
fVGJyY5BCVuOXUJgH5iyzdgIHhSuOxHMd2oCGvxrV9LD3MmNvMBdxIKLH7SHce5V
DhpqTGx0WNG9LVd3IUZP6TkdgMMinY1wgSzL2Eq7qlW0obMBYY9puAV2gshj6lGP
rwIBlkoR0O0LacG4YMWuQAcOVbqGtC7NkLJM14n70YErb3QPMfl0ChaiVSHJYUPP
TC5F9V9kkFltb1lJeYWDJuWPCIR9+vq6JsciYjyyGQKBgQD4wCdENUeg83t7uCtE
l7qVmxN3z15C/zWgUzRtqK/YInXKx4daQA3Aj3NwBRzCRH5KJouhcFgWDjAHIdzB
HsVBHPZXleBicm09JjIIKBZ+g+nUHZEpvClTgQNRNH7C2eMDpO0HPSTF2nORXWxb
GQkVDsfUG8bYJCdnB7L8BY2vHQKBgQDBNa3l9U6cJ16MSdf/E9h+2STR4yN8vn9m
qD89aMKkMtKyve3oVPdVOiKUhPMXkK8x3IUYU+IpBxiQXGe1F9rgAFBY2vWQ9LMQ
eMsChRcrP/tSaEWJZZNMzmtsDiJq+vOHA9WemvvxB9DvLoCZu1gPpDdsXKCTYiV8
swv2w9ZpuQKBgBvqnL2H6TkD+ljBK4HwMU128PFiQWbtc1xB2kFwTAPKokOWrvcO
9zwkHUV2HWsj+rRhrQv6KriW8Qbr4vV9eY+8K11bAaqqwt24+qZ1sUiTj1tx0gfI
CS9I7FFhvdQqVdLj4IIOd6EIyi2HOZDjt2Q4m26Pi3pYXF+wuoKUMPl1AoGAGznI
NnZZzHFTxmsFb+FJCZ7prFXYg1SIuVuOBcZEX0T2Ic/XvXxzmePmSY1uf+yYc2tC
qgnv/Z4NXRJYXtFsu1HwAIViQznoHbMX0FQWzrZmYNdmrRTOK+2Of5yCRxbzyBvH
N2FZjT5vt7SS1Jbsss+OK8vlqL8Uzzyfu/ceuKkCgYEAmWBTmlikPfI/64k/dKi/
Kf86RRzV1oXpKSIA2bh+nuk3X7vdP04s8Eop3UGBMD3qq6C0TAMPM7UdbvM1LfG6
iAY48rnKhmeDr1MJkjvHybjOawftMjW1A2/UTdBSDevYd1bnIMYAFJl4dcmRadSE
PLqGDB6VSIOEA+T8Ie3IeH8=
-----END PRIVATE KEY-----
"""
def decrypt_request(encrypted_flow_data_b64, encrypted_aes_key_b64, initial_vector_b64):
flow_data = b64decode(encrypted_flow_data_b64)
iv = b64decode(initial_vector_b64)
# Decrypt the AES encryption key
encrypted_aes_key = b64decode(encrypted_aes_key_b64)
private_key = load_pem_private_key(PRIVATE_KEY, None, default_backend())
aes_key = private_key.decrypt(encrypted_aes_key, OAEP(
mgf=MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None))
# Decrypt the Flow data
encrypted_flow_data_body = flow_data[:-16]
encrypted_flow_data_tag = flow_data[-16:]
decryptor = Cipher(algorithms.AES(aes_key),
modes.GCM(iv, encrypted_flow_data_tag)).decryptor()
decrypted_data_bytes = decryptor.update(
encrypted_flow_data_body) + decryptor.finalize()
decrypted_data = json.loads(decrypted_data_bytes.decode("utf-8"))
return decrypted_data, aes_key, iv
def encrypt_response(response, aes_key, iv):
# Flip the initialization vector
flipped_iv = bytearray()
for byte in iv:
flipped_iv.append(byte ^ 0xFF)
# Encrypt the response data
encryptor = Cipher(algorithms.AES(aes_key),
modes.GCM(flipped_iv)).encryptor()
data = encryptor.update(json.dumps(response).encode("utf-8")) + encryptor.finalize() + encryptor.tag
return b64encode(
data
).decode("utf-8")
encrypted_flow_data_b64 = 'H78/q8TCjizJhK8yt8tPEHG2QzArPsEFIoLajXWuPb5s6RA0QfHE7JMFFw3hTNh1byNSwjGVic8r2V9j76q4Et8UM9/bMCsF3UnXEzPNTZgQH4FHUIyjNQ=='
encrypted_aes_key_b64 = 'rjbs78LfWHLLqay/Fe4ofEisbMhCINmdUMlwXREuBGfRVRQzDmfEMoMFdCwLaX66nh/x7lJDyyjQZ+XA50gN1hEuDji0qbyGgpzZUUUfkxqYsgDW61Nf93cWvCPIRsgfuP5Brggoqr3slfRLbLPUOjkYOaof7lGJqHHbBeIb4RgEOAaIOXCA+84W5wrU/hmODoGNQ5FV7zjRdOpd8vX6JXcQ46LCLtmfPr0zx0NVetP8qvM7sn2X7FXlZtebut3k4XWkWQd3GEyWw5MEm4a4TJGtrXBAqcl7jsbTExgfVnVFD6saRKCoy2m6FqouMw9CzU5KyNItWhXkE4HtzKQilA=='
initial_vector_b64 = 'S84bbuqcCYjCtLECg9sq+A=='
decrypted_data, aes_key, iv = decrypt_request(encrypted_flow_data_b64, encrypted_aes_key_b64, initial_vector_b64)
json_string = '{"version":"3.0","screen":"SENDER_DETAIL","data":{"areas":[{"id":"0","title":"Testing"},{"id":"1","title":"Testo"}],"cities":[{"id":"0","title":"Sweeto"},{"id":"1","title":"LEts Go"}]}}'
response_object = json.loads(json_string)
print(response_object)
print(aes_key)
print(iv)
print(encrypt_response(response_object, aes_key, iv))
#Expected Results:
# response_object = {'version': '3.0', 'screen': 'SENDER_DETAIL', 'data': {'areas': [{'id': '0', 'title': 'Testing'}, {'id': '1', 'title': 'Testo'}], 'cities': [{'id': '0', 'title': 'Sweeto'}, {'id': '1', 'title': 'LEts Go'}]}}
# encrypt_response(response_object, aes_key, iv) = '+8JsaVL25x4CIadr+eprJzOmYr3BZMEoykdUkFn3RXz5OUQQkYRa2BbzM3gqV9skRYU+klYX+6VeLS9oDLNAP8CI7HJYwkqxnDRodwxL1LHKfzn4P+9yjdepVSkXg5020OQMnZru8VpDxIjlUECiaDCkTgFjXYvhyfxU/nqwhX8PvILfAvSq8ZRd+CV6qLItGQcPBQ7PVBQqtamdWDtSOxWDOe8bK/eYtUWTfVnE29RsVOMrby58br/kLhCMNbGwJYXdDxTpZoeAqg2YKCTPe/eVv9qmXRGEeSXXoiGllw=='
func aesEncryption(aesKey []byte, iv []byte, plainText []byte) string {
flippedIV := make([]byte, len(iv))
for i, b := range iv {
flippedIV[i] = b ^ 0xFF
}
block, _ := aes.NewCipher(aesKey)
mode := cipher.NewCBCEncrypter(block, flippedIV)
padder := padding.NewPkcs7Padding(block.BlockSize())
paddedPlainText, _ := padder.Pad(plainText)
ciphertext := make([]byte, len(paddedPlainText))
mode.CryptBlocks(ciphertext, paddedPlainText)
encodedText := base64.StdEncoding.EncodeToString(ciphertext)
return encodedText
预期的加密响应
'+8JsaVL25x4CIadr+eprJzOmYr3BZMEoykdUkFn3RXz5OUQQkYRa2BbzM3gqV9skRYU+klYX+6VeLS9oDLNAP8CI7HJYwkqxnDRodwxL1LHKfzn4P+9yjdepVSkXg5020OQMnZru8VpDxIjlUECiaDCkTgFjXYvhyfxU/nqwhX8PvILfAvSq8ZRd+CV6qLItGQcPBQ7PVBQqtamdWDtSOxWDOe8bK/eYtUWTfVnE29RsVOMrby58br/kLhCMNbGwJYXdDxTpZoeAqg2YKCTPe/eVv9qmXRGEeSXXoiGllw=='
我从 Go 使用此输入得到的输出是:
8AhYU9io9kn9SUVWIS00NW/i8/rBYZjXnLjxfad6hZvUXGhilig7/HsM5y6f5swcCJule+eCXROIs55W+IwLkvVTB3kxjL9FC/wJrSw76FJjY21I1AymaWFJC7rjt+2aPHWFtoYAQIwhvWu9oqqzJsTQce2GqRAT/1mK7N/Pa5HwKt3M4H/mrQzOtMa7BbGcI1Sf20eFmWcavz0VoLs+mVfDGk6FonLKs+WwsBNJ2lwIxDhmYleHwioviZGoOml2
我们在 Go 中添加了 Flow 端点示例以及 Python、NodeJS、PHP、Java、C# 中的现有示例
https://developers.facebook.com/docs/whatsapp/flows/guides/implementingyourflowendpoint#go-example