我正在尝试使用椭圆曲线密码图 ECDiffieHellman 解密消息,使用 KDFX963 作为密钥派生函数 (KDF)(在 ANSI-X9.63-KDF http://www.secg.org/sec1-v2.pdf中定义)
但我正在努力完成这项工作。我非常需要这样的方法:
DecryptMessage(string tokenFromPayload, string publicKeyStr, string privateKeyStr){
// Generate an ephemeral key from the public and private key
// Decrypt payload with the ephemeral key
}
有关解密消息的算法的一些额外信息:
- 椭圆曲线:SECP384R1;命名为Curves.brainpoolP384r1
- 密码:AES 模式:GCM
- 密钥大小:32
- Mac 尺寸 = 16
- 密钥导出函数:ANSI-X9.63-KDF
- 哈希:Sha256(长度 32)
我有下面的 Python 代码正在执行解密消息所需的操作,但我需要在 C# 中使用它。
import base64
import binascii
import json
import os
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.ciphers import algorithms, Cipher, modes
from cryptography import utils
from hashlib import sha256
from math import ceil
class BCAuthCrypto:
"""A class containing a number of handlers for the secp384r1 ECC algorithm in Python"""
curve = ec.SECP384R1()
cipher_key_size = 32
mac_size = 16
backend = default_backend()
def ITOSP(self, longint, length):
"""ITOSP, short for Integer-to-Octet-String Primitive, converts a non-negative integer
to an octet string of a specified length. This particular function is defined in the
PKCS #1 v2.1: RSA Cryptography Standard (June 14, 2002)
https://www.cryptrec.go.jp/cryptrec_03_spec_cypherlist_files/PDF/pkcs-1v2-12.pdf"""
hex_string = "%X" % longint
assert len(hex_string) <= 2 * length, "ITOSP function: Insufficient length for encoding"
return binascii.a2b_hex(hex_string.zfill(2 * length))
def KDFX963(self, inbyte_x, shared_data, key_length, hashfunct=sha256, hash_len=32):
"""KDFX963 is a key derivation function (KDF) that takes as input byte sequence inbyte_x
and additional shared data shared_data and outputs a byte sequence key of length
key_length. This function is defined in ANSI-X9.63-KDF, and this particular flavor of
KDF is known as X9.63. You can read more about it from:
http://www.secg.org/sec1-v2.pdf"""
assert key_length >= 0, "KDFX963 function: key_length should be positive integer"
k = key_length / float(hash_len)
k = int(ceil(k))
acc_str = ""
for i in range(1, k+1):
h = hashfunct()
h.update(inbyte_x)
h.update(self.ITOSP(i, 4))
h.update(shared_data)
acc_str = acc_str + h.hexdigest()
return acc_str[:key_length * 2]
def decrypt(self, cipher_text_b64, private_key):
"""Decrypt takes input base64-encoded data input cipher_text_b64 and private key
private_key and outputs plain text data, throws exception on error"""
cipher = base64.b64decode(cipher_text_b64)
ephemeral_key_len = ((self.curve.key_size + 7) // 8) * 2 + 1
ephemeral_key_numbers = ec.EllipticCurvePublicNumbers.from_encoded_point(self.curve, cipher[:ephemeral_key_len])
ephemeral_key = ephemeral_key_numbers.public_key(self.backend)
shared_key = private_key.exchange(ec.ECDH(), ephemeral_key)
V = cipher[:ephemeral_key_len]
K = binascii.unhexlify(self.KDFX963(shared_key, V, self.cipher_key_size + self.mac_size))
K1 = K[:self.cipher_key_size]
K2 = K[self.cipher_key_size:]
T = cipher[ephemeral_key_len:]
enc_data = T[:len(T) - self.mac_size]
tag = T[-self.mac_size:]
decryptor = Cipher(algorithms.AES(K1), modes.GCM(K2, tag), backend=self.backend).decryptor()
plain_text = decryptor.update(enc_data) + decryptor.finalize()
return plain_text
def decrypt_auth_token(tokenFromPayload, public_key_str, private_key_str):
"""Retrive the auth token and decrypt it, in a way that does not specify the name of the service."""
bc_crypto = BCAuthCrypto()
public_number = ec.EllipticCurvePublicNumbers.from_encoded_point(bc_crypto.curve, base64.b64decode(public_key_str))
private_number = ec.EllipticCurvePrivateNumbers(utils.int_from_bytes(base64.b64decode(private_key_str), "big"), public_number)
private_key = private_number.private_key(bc_crypto.backend)
token = bc_crypto.decrypt(tokenFromPayload, private_key)
print "token (decrypted): %s" % token
return token
希望有一个密码学天才可以帮助我,或者是“Python To C#”专家。谢谢。