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

基于C语言解析EMV卡GPO响应获取各卡AFL的技术问询

Alright, let's tackle parsing the AFL (Access File Locator) from GET PROCESSING OPTIONS (GPO) responses in C—since you don't have Java tools to lean on, we'll build a straightforward, card-agnostic parser that handles those three card types you mentioned.

Parsing AFL from GPO Responses in C

First, a quick recap: GPO responses use BER-TLV formatting. The AFL is always stored under the 0x94 TLV tag. The response might be wrapped in a container tag: either 0x77 (Response Message Template Format 2, like your HelloBank/PayPal examples) or 0x80 (Response Message Template Format 1, like your PostePay example). Our goal is to drill down through these containers to extract the 0x94 tag's value.

Step 1: Core TLV Parsing Function

We'll start with a reusable function to hunt for a specific TLV tag, including recursive parsing of container tags (0x77/0x80):

#include <stdint.h>
#include <string.h>

/**
 * Finds a target TLV tag in BER-TLV formatted data
 * @param data: Pointer to raw TLV data
 * @param data_len: Length of the raw data
 * @param target_tag: Tag to search for (e.g., 0x94 for AFL)
 * @param value: Output pointer to the tag's value
 * @param value_len: Output length of the tag's value
 * @return 0 on success, -1 if tag not found
 */
int find_tlv_tag(const uint8_t *data, size_t data_len, uint8_t target_tag, const uint8_t **value, size_t *value_len) {
    size_t offset = 0;
    while (offset < data_len) {
        // Parse single-byte tag (covers 0x80, 0x77, 0x94 which we care about)
        uint8_t current_tag = data[offset++];
        
        // Parse length (handle single and multi-byte lengths)
        size_t len = data[offset++];
        if (len & 0x80) {
            int num_len_bytes = len & 0x7F;
            len = 0;
            for (int i = 0; i < num_len_bytes; i++) {
                len = (len << 8) | data[offset++];
            }
        }
        
        // Check if we found our target tag
        if (current_tag == target_tag) {
            *value = &data[offset];
            *value_len = len;
            return 0;
        }
        
        // If this is a container tag, recursively search its contents
        if (current_tag == 0x77 || current_tag == 0x80) {
            int ret = find_tlv_tag(&data[offset], len, target_tag, value, value_len);
            if (ret == 0) return 0;
        }
        
        // Skip past the current tag's value to move to the next TLV element
        offset += len;
    }
    return -1;
}

Step 2: GPO-Specific AFL Extraction

Next, wrap the core function to handle GPO responses (we'll strip the trailing success status word 90 00 first):

/**
 * Extracts AFL from a raw GPO response
 * @param gpo_response: Raw GPO response bytes (including status word)
 * @param response_len: Total length of the GPO response
 * @param afl_data: Output pointer to the AFL bytes
 * @param afl_len: Output length of the AFL data
 * @return 0 on success, -1 on error
 */
int parse_gpo_afl(const uint8_t *gpo_response, size_t response_len, const uint8_t **afl_data, size_t *afl_len) {
    // Validate response length (needs at least status word + some data)
    if (response_len < 2) return -1;
    
    // Strip trailing status word (90 00 is standard success for GPO)
    const uint8_t *tlv_data = gpo_response;
    size_t tlv_len = response_len - 2;
    
    // Search for the 0x94 tag (AFL)
    return find_tlv_tag(tlv_data, tlv_len, 0x94, afl_data, afl_len);
}

Testing with Your Card Examples

Let's verify with your three cases:

A) HelloBank Response

Raw response (full with status word):
77 12 82 02 38 00 94 0C 10 02 04 01 18 01 01 00 20 01 01 00 90 00

  • parse_gpo_afl will find the 0x94 tag with length 0xC (12 bytes).
  • AFL data: 10 02 04 01 18 01 01 00 20 01 01 00

B) PayPal Response

Raw response (full with status word):
77 12 82 02 39 00 94 0C 18 01 01 00 20 01 01 00 28 01 03 01 90 00

  • 0x94 tag length is 0xC (12 bytes).
  • AFL data: 18 01 01 00 20 01 01 00 28 01 03 01

C) PostePay Response (Starts with 0x80)

Even though the response starts with 0x80 (Template Format 1), the recursive parsing in find_tlv_tag will drill into the 0x80 container and locate the 0x94 tag just like the other cases.

Edge Case Notes

  • Multi-byte Tags: The current code handles single-byte tags (which covers all tags we need for AFL extraction). If you encounter cards with extended multi-byte tags later, you can expand the tag parsing logic.
  • Non-Standard Status Words: Some cards might return alternative success status words. If needed, adjust the parse_gpo_afl function to check for valid status words before stripping them.
  • Variable AFL Length: AFL length is defined by the 0x94 tag's length field—our code automatically adapts to whatever length the card returns.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:54:17