当前位置: 首页 > 知识库问答 >
问题:

使用secp384r1 ECC算法和KDFX963解密消息

微生俊材
2023-03-14

我尝试使用椭圆曲线密码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
}

关于解密消息的算法的一些额外信息:

    < li >椭圆曲线:SECP384R1named curves . brain pool p384r 1 < li >密码:AES模式:GCM < li >密钥大小:32 < li>Mac Size = 16 < li >密钥派生函数:ANSI-X9.63-KDF < li >哈希: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到C#”专家。谢谢

共有1个答案

韦星文
2023-03-14

得到我的答案那里解密苹果商业聊天身份验证令牌

namespace AppleBusinessChat45
{
    class Program
    {
        static void Main(string[] args)
        {
            var privateKey = "pX/BvdXXUdpC79mW/jWi10Z6PJb5SBY2+aqkR/qYOjqgakKsqZFKnl0kz10Ve+BP";
            var token = "BDiRKNnPiPUb5oala31nkmCaXMB0iyWy3Q93p6fN7vPxEQSUlFVsInkJzPBBqmW1FUIY1KBA3BQb3W3Qv4akZ8kblqbmvupE/EJzPKbROZFBNvxpvVOHHgO2qadmHAjHSmnxUuxrpKxopWnOgyhzUx+mBUTao0pcEgqZFw0Y/qZIJPf1KusCMlz5TAhpjsw=";

            // #####
            // ##### Step 1
            // #####
            var decodedToken = Convert.FromBase64String(token);
            var decodedEphemeralPublicKey = decodedToken.Take(97).ToArray();
            var encodedEphemeralPublicKeyCheck = Convert.ToBase64String(decodedEphemeralPublicKey);

            if (encodedEphemeralPublicKeyCheck != "BDiRKNnPiPUb5oala31nkmCaXMB0iyWy3Q93p6fN7vPxEQSUlFVsInkJzPBBqmW1FUIY1KBA3BQb3W3Qv4akZ8kblqbmvupE/EJzPKbROZFBNvxpvVOHHgO2qadmHAjHSg==")
                throw new Exception("Public key check failed");

            X9ECParameters curveParams = ECNamedCurveTable.GetByName("secp384r1");
            ECPoint decodePoint = curveParams.Curve.DecodePoint(decodedEphemeralPublicKey);
            ECDomainParameters domainParams = new ECDomainParameters(curveParams.Curve, curveParams.G, curveParams.N, curveParams.H, curveParams.GetSeed());
            ECPublicKeyParameters ecPublicKeyParameters = new ECPublicKeyParameters(decodePoint, domainParams);

            var x = ecPublicKeyParameters.Q.AffineXCoord.ToBigInteger();
            var y = ecPublicKeyParameters.Q.AffineYCoord.ToBigInteger();

            if (!x.Equals(new BigInteger("8706462696031173094919866327685737145866436939551712382591956952075131891462487598200779332295613073905587629438229")))
                throw new Exception("X coord check failed");

            if (!y.Equals(new BigInteger("10173258529327482491525749925661342501140613951412040971418641469645769857676705559747557238888921287857458976966474")))
                throw new Exception("Y coord check failed");

            Console.WriteLine("Step 1 complete");

            // #####
            // ##### Step 2
            // #####
            var privateKeyBytes = Convert.FromBase64String(privateKey);
            var ecPrivateKeyParameters = new ECPrivateKeyParameters("ECDHC", new BigInteger(1, privateKeyBytes), domainParams);
            var privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(ecPrivateKeyParameters);
            var ecPrivateKey = (ECPrivateKeyParameters) PrivateKeyFactory.CreateKey(privateKeyInfo);

            IBasicAgreement agree = AgreementUtilities.GetBasicAgreement("ECDHC");
            agree.Init(ecPrivateKey);
            BigInteger sharedKey = agree.CalculateAgreement(ecPublicKeyParameters);
            var sharedKeyBytes = sharedKey.ToByteArrayUnsigned();
            var sharedKeyBase64 = Convert.ToBase64String(sharedKeyBytes);

            if (sharedKeyBase64 != "2lvSJsBO2keUHRfvPG6C1RMUmGpuDbdgNrZ9YD7RYnvAcfgq/fjeYr1p0hWABeif")
                throw new Exception("Shared key check failed");

            Console.WriteLine("Step 2 complete");

            // #####
            // ##### Step 3
            // #####
            var kdf2Bytes = Kdf2(sharedKeyBytes, decodedEphemeralPublicKey);
            var kdf2Base64 = Convert.ToBase64String(kdf2Bytes);

            if (kdf2Base64 != "mAzkYatDlz4SzrCyM23NhgL/+mE3eGgfUz9h1CFPhZOtXequzN3Q8w+B5GE2eU5g")
                throw new Exception("Kdf2 failed");

            Console.WriteLine("Step 3 complete");

            // #####
            // ##### Step 4
            // #####
            var decryptionKeyBytes = kdf2Bytes.Take(32).ToArray();
            var decryptionIvBytes = kdf2Bytes.Skip(32).ToArray();

            var decryptionKeyBase64 = Convert.ToBase64String(decryptionKeyBytes);
            var decryptionIvBase64 = Convert.ToBase64String(decryptionIvBytes);

            if (decryptionKeyBase64 != "mAzkYatDlz4SzrCyM23NhgL/+mE3eGgfUz9h1CFPhZM=")
                throw new Exception("Decryption key check failed");

            if (decryptionIvBase64 != "rV3qrszd0PMPgeRhNnlOYA==")
                throw new Exception("Decryption iv check failed");

            var encryptedDataBytes = decodedToken.Skip(97).Take(decodedToken.Length - 113).ToArray();
            var tagBytes = decodedToken.Skip(decodedToken.Length - 16).ToArray();

            var encryptedDataBase64 = Convert.ToBase64String(encryptedDataBytes);
            var tagBase64 = Convert.ToBase64String(tagBytes);

            if (encryptedDataBase64 != "afFS7GukrGilac6DKHNTH6YFRNqjSlwSCpkXDRj+")
                throw new Exception("Encrypted data check failed");

            if (tagBase64 != "pkgk9/Uq6wIyXPlMCGmOzA==")
                throw new Exception("Tag check failed");

            KeyParameter keyParam = ParameterUtilities.CreateKeyParameter("AES", decryptionKeyBytes);
            ParametersWithIV parameters = new ParametersWithIV(keyParam, decryptionIvBytes);
            IBufferedCipher cipher = CipherUtilities.GetCipher("AES/GCM/NoPadding");
            cipher.Init(false, parameters);
            var resultBytes = cipher.DoFinal(encryptedDataBytes.Concat(tagBytes).ToArray());
            var resultBase64 = Convert.ToBase64String(resultBytes);
            var resultString = Strings.FromByteArray(resultBytes);

            if (resultString != "xXTi32iZwrQ6O8Sy6r1isKwF6Ff1Py")
                throw new Exception("Decryption failed");

            Console.WriteLine("Step 4 complete");
            Console.WriteLine(resultString);

            Console.WriteLine();
            Console.WriteLine("Done... press any key to finish");
            Console.ReadLine();
        }

        static byte[] Kdf2(byte[] sharedKeyBytes, byte[] ephemeralKeyBytes)
        {
            var gen = new Kdf2BytesGenerator(new Sha256Digest());
            gen.Init(new KdfParameters(sharedKeyBytes, ephemeralKeyBytes));

            byte[] encryptionKeyBytes = new byte[48];
            gen.GenerateBytes(encryptionKeyBytes, 0, encryptionKeyBytes.Length);
            return encryptionKeyBytes;
        }
    }
}
 类似资料:
  • 我正在为我的应用程序制作加密/解密模块。我按照这个教程 它没有给出任何错误,也没有显示输出。 日志文件 MainActivity.Java AESHelper.Java } AESHelper.java:52 还有AESHelper.java:25

  • 问题内容: 我目前正在使用Java创建应用程序,我用Java搜索了密码加密,但是结果是如此巨大,以至于我感到不知所措。如何使用Java加密和解密密码?加密和解密密码的最佳实践是什么?我猜MD5不是一种方法,因为它是一种单向哈希。我使用struts2作为框架,想知道它们是否提供密码加密 问题答案: 更新时间 : 试试JBCrypt: 从此处下载jBCrypt-0.3,有关更多详细信息,请查看READ

  • 我目前正在使用Java创建应用程序,我用java谷歌了密码加密,但结果是如此巨大,我感到不知所措。我将如何使用Java加密和解密密码?加密和解密密码的最佳实践是什么?我猜MD5是行不通的,因为它是单向哈希。我使用struts2作为我的框架,想知道他们是否提供密码加密

  • 我想加密test.txt文件我正在使用这个java类进行加密和解密。在我的目录中,我有三个文件private.txt用于保存私钥,public.txt用于公钥,test.txt用于加密。

  • 最近,我一直在尝试教育自己如何使用Vigenere密码进行加密和解密。 我已成功加密该邮件,以下是我为实现加密所采取的步骤: 加密密钥:设置 消息:绝密 步骤1:键的数字表示为18、4、19(使用下表) E:P x k->C是加密函数 D:C x K->P为解密函数 明文:绝密 多谢了。

  • 我有一条在java上使用以下代码加密的kafka消息: 现在我正在尝试在我已经知道私钥的解码消息上使用python对其进行解码。我尝试使用(因为我使用的是python3和仅适用于2. x)像在他们的文档中一样使用此代码,但它不起作用: 我得到了这个错误代码:我试图寻找一种方法使私钥成为JWK对象,但找不到。 我知道我的消息是JWE,因为它被4个点分割,当我对第一部分进行base64解码时,我得到了