You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#实现PACE PIN通用映射时遇6984(DATA_INVALID)错误求助

使用ECC实现带通用映射的PACE PIN认证时发送PKPCD,map遭遇6984错误排查

我正尝试使用椭圆曲线实现带通用映射的PACE PIN认证,在执行「发送PKPCD,map并接收PKPICC,map」步骤时遇到6984错误。6984错误表示DATA_INVALID:给定数据或卡内数据(如保存的挑战值)无效。

参考资料

  • GitHub文档
  • ICAO 9303第11部分手册

自定义卡ECC参数

Using ECC-NIST 256 curve for the domain parameters

# Private ECC key (Generated from a RNG)
d_pace_ecdh_card_private=0029482318BE67844AE13D6C2CD672AE69525F9016496DF15AF141BB26E901EB
prime=FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF
a=FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC
order=FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551
b=5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B
G_X=
basepoint=6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5
# Calculate Ecc public key (Q=d_pace_ecdh_card_private*basepoint)
pace_ecdh_public=046CEC918BFBE1198005718DEA22D2139C856B66326B66A8AF769DAADB4D4F439B56A161713158746F8D3117F097972B1F9CB2382E54A3AF2D61FAA30ED1FEF436

实现代码

public void paceGenericMapping()
{
    // Paramètres du domaine pour la courbe ECC-NIST 256
    X9ECParameters curve = SecNamedCurves.GetByName("secp256r1");
    // Utilisation des paramètres déjà connus

    Org.BouncyCastle.Math.BigInteger prime = new Org.BouncyCastle.Math.BigInteger("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", 16);
    Org.BouncyCastle.Math.BigInteger a = new Org.BouncyCastle.Math.BigInteger("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", 16);
    Org.BouncyCastle.Math.BigInteger order = new Org.BouncyCastle.Math.BigInteger("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", 16);
    Org.BouncyCastle.Math.BigInteger b = new Org.BouncyCastle.Math.BigInteger("5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", 16);
    Org.BouncyCastle.Math.BigInteger G_X = new Org.BouncyCastle.Math.BigInteger("6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", 16);
    Org.BouncyCastle.Math.BigInteger G_Y = new Org.BouncyCastle.Math.BigInteger("4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", 16);
    Org.BouncyCastle.Math.EC.ECPoint basePoint = curve.Curve.CreatePoint(G_X, G_Y);

    
    ECDomainParameters domainParams = new ECDomainParameters(curve.Curve, basePoint, order, curve.H, curve.GetSeed());

    //  • Read EF.DIR and EF.CardAccess (applet capabilities)
    string selectEF_F000 = executeCommande("00A40000023F00");
    string selectEF_CardAccess = executeCommande("00a4020c02011c");
    string read_binary_1 = executeCommande("00b0000005");
    string read_binary_2 = executeCommande("00b000055b");

    //  • Select algorithm (INS 22)
    string setMSE = executeCommande("0022c1a412800a04007f0007020204020283010384010c");

    //  • The host requests PACE for authentication, possibly giving a preference : 
    string paceAuthenticationREQUEST = executeCommande("10860000027c0000");

    //  •   The card responds with a 128-bit (16 byte) random number (nonce) encrypted with PACE_nonce_AES128key  : 7C 12 80 10 <encrypted_nonce>
    int startIndex = paceAuthenticationREQUEST.IndexOf("7C128010") + "7C128010".Length;

    // Trouver l'index de fin de la sous-chaîne
    int endIndex = paceAuthenticationREQUEST.IndexOf("9000", startIndex);

    // Extraire la sous-chaîne : representant Key: z - encrypted nonce (z [PACE])
    string encryptedNonce = paceAuthenticationREQUEST.Substring(startIndex, endIndex - startIndex);

    //  the host decrypts the 128-bit nonce with PACE_nonce_AES128key derived from user input as described above
    byte[] bytesEncryptedNonce = StringToByteArray(encryptedNonce);

    // Key: K - derived key from shared secret : trouver la clé dérivée du PIN
    string derivedKeySH = calculerSHA1("3132333400000003");
    byte[] bytesDerivedKeySH = StringToByteArray(derivedKeySH);

    //  • [decrypt nonce nonce]
    byte[] bytesDecryptedNonce = decryptAES(bytesEncryptedNonce, bytesDerivedKeySH);
    string decryptedNonce = byteToHexStr(bytesDecryptedNonce);
    Org.BouncyCastle.Math.BigInteger nonce = new Org.BouncyCastle.Math.BigInteger(decryptedNonce, 16);

    //  • [generate random number as private key SKPCD for DHKA]           
    SecureRandom random = new SecureRandom();
    Org.BouncyCastle.Math.BigInteger SKPCD = new Org.BouncyCastle.Math.BigInteger(domainParams.Curve.Order.BitLength, random).Mod(domainParams.Curve.Order);

    // •  [calculate ephermeral PKPCD = BasePoint G * SKPCD]
    Org.BouncyCastle.Math.EC.ECPoint PKPCD = domainParams.G.Multiply(SKPCD);
    // Convertir les coordonnées X et Y en hexadécimal
    string PKPCDXHex = PKPCD.XCoord.ToBigInteger().ToString(16);
    string PKPCDYHex = PKPCD.YCoord.ToBigInteger().ToString(16);         

    //  • Send PKPCD and Receive PKPICC from card
    string requestPKicc = "10860000457C43814104" + PKPCDXHex + PKPCDYHex + "00";
    string reponsePKicc = executeCommande(requestPKicc);

    // Définir les positions de début et de fin de la sous-chaîne
       int entete = 10; // Après les 4 premiers octets
       int sw = reponsePKicc.Length - 4; // Avant les 4 derniers octets

    // Extraire la sous-chaîne
     reponsePKicc = reponsePKicc.Substring(entete, sw - entete);         

    string PKICCXHex = reponsePKicc.Substring(0, reponsePKicc.Length/2);
    string PKICCYHex = reponsePKicc.Substring(reponsePKicc.Length / 2);
   
    Org.BouncyCastle.Math.EC.ECPoint PKPICC = curve.Curve.CreatePoint(new Org.BouncyCastle.Math.BigInteger(PKICCXHex, 16), new Org.BouncyCastle.Math.BigInteger(PKICCYHex, 16));

    //  • [build shared secret: H = PKPICC * SKPCD = G * SKPICC * SKPCD]
    Org.BouncyCastle.Math.EC.ECPoint H = PKPICC.Multiply(SKPCD);

    //  • [build new base point:] :  Gmap = G * s + H = G * s + G * SKPICC * SKPCD = G * (s + SKPICC * SKPCD)
    Org.BouncyCastle.Math.EC.ECPoint Gmap = basePoint.Multiply(nonce);           Gmap = Gmap.Add(H);

    //  • [generate random number as private key SKPCD,map for DHKA]            
    Org.BouncyCastle.Math.BigInteger SKPCDMap = new Org.BouncyCastle.Math.BigInteger(Gmap.Curve.Order.BitLength, random).Mod(Gmap.Curve.Order);

    //  • [calculate ephermeral PKPCD,map = BasePoint Gmap * SKPCD,map]
    
    Org.BouncyCastle.Math.EC.ECPoint PKPCDMap = Gmap.Multiply(SKPCDMap);
    // Convertir les coordonnées X et Y en hexadécimal
    string PKPCDMapXHex = PKPCDMap.XCoord.ToBigInteger().ToString(16);
    string PKPCDMapYHex = PKPCDMap.YCoord.ToBigInteger().ToString(16);

    //  • Send PKPCD,map and Receive PKPICC,map from card
    string requestPKpcdmap = "10860000457c43834104" + PKPCDMapXHex + PKPCDMapYHex + "00";
    string responsePKpcdmap = executeCommande(requestPKpcdmap);

}

恳请协助排查该6984错误的原因及解决方法。

内容的提问来源于stack exchange,提问作者Bouls

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 07:47:33