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

如何从DER或PEM格式的ECC私钥文件中提取OCTET STRING的字符数组或字节数组

Extract ECC Private Key (OCTET STRING) from DER/PEM using OpenSSL in C

Hey there! I’ve worked with OpenSSL’s ECC APIs quite a bit, so let’s break down how to grab that OCTET STRING value you need from your ECC private key file.

First, let’s clarify what that OCTET STRING represents: it’s the raw private key value for your ECC curve (in your case, secp256r1, since the OID 1.2.840.10045.3.1.7 maps directly to this curve). When you use PEM_read_ECPrivateKey or d2i_ECPrivateKey, OpenSSL parses the DER/PEM into an EC_KEY struct, and we can extract the raw private key straight from there.


Step 1: Load the DER/PEM file into an EC_KEY structure

First, we need to get your key file into OpenSSL’s native EC_KEY type. Here’s how to handle both formats:

For PEM files:

#include <openssl/ec.h>
#include <openssl/pem.h>
#include <openssl/bn.h>

EC_KEY *load_pem_ecc_key(const char *file_path) {
    FILE *fp = fopen(file_path, "r");
    if (!fp) return NULL;

    EC_KEY *key = PEM_read_ECPrivateKey(fp, NULL, NULL, NULL);
    fclose(fp);
    return key;
}

For DER files:

EC_KEY *load_der_ecc_key(const char *file_path) {
    FILE *fp = fopen(file_path, "rb");
    if (!fp) return NULL;

    EC_KEY *key = d2i_ECPrivateKey_fp(fp, NULL);
    fclose(fp);
    return key;
}

Step 2: Extract the raw private key (OCTET STRING) from EC_KEY

The private key is stored as a BIGNUM inside the EC_KEY struct. We can grab a pointer to it with EC_KEY_get0_private_key(), then convert it to either a hex string or byte array as you need.

Option 1: Get the private key as a hex string (matches your first output format)

char *get_ecc_private_key_hex(EC_KEY *key) {
    if (!key) return NULL;

    const BIGNUM *priv_key = EC_KEY_get0_private_key(key);
    if (!priv_key) return NULL;

    // Convert BIGNUM to a hex string (matches your ASN.1 OCTET STRING value)
    char *hex_str = BN_bn2hex(priv_key);
    return hex_str; // Don't forget to free this with OPENSSL_free() later!
}

Option 2: Get the private key as a byte array (matches your second output format)

unsigned char *get_ecc_private_key_bytes(EC_KEY *key, size_t *out_len) {
    if (!key || !out_len) return NULL;

    const BIGNUM *priv_key = EC_KEY_get0_private_key(key);
    if (!priv_key) return NULL;

    // Calculate the required length for the byte array
    int key_len = BN_num_bytes(priv_key);
    if (key_len <= 0) return NULL;

    unsigned char *key_bytes = OPENSSL_malloc(key_len);
    if (!key_bytes) return NULL;

    // Write the BIGNUM to the byte array in big-endian order (standard for ECC)
    BN_bn2bin(priv_key, key_bytes);
    *out_len = key_len;

    return key_bytes; // Remember to free this with OPENSSL_free()!
}

Step 3: Full Working Example

Here’s a complete snippet that loads a DER file, extracts both formats, and prints them out:

#include <stdio.h>
#include <openssl/ec.h>
#include <openssl/pem.h>
#include <openssl/bn.h>
#include <openssl/crypto.h>

int main() {
    const char *der_file = "your_private_key.der";
    EC_KEY *key = load_der_ecc_key(der_file);
    if (!key) {
        printf("Failed to load DER key\n");
        return 1;
    }

    // Print hex string format
    char *hex_key = get_ecc_private_key_hex(key);
    if (hex_key) {
        printf("// Hex string format\n");
        printf("privatekey = \"%s\";\n", hex_key);
        OPENSSL_free(hex_key);
    }

    // Print byte array format
    size_t byte_len;
    unsigned char *byte_key = get_ecc_private_key_bytes(key, &byte_len);
    if (byte_key) {
        printf("\n// Byte array format\n");
        printf("privatekey = {");
        for (size_t i = 0; i < byte_len; i++) {
            if (i > 0) printf(",");
            printf("0x%02X", byte_key[i]);
        }
        printf("};\n");
        OPENSSL_free(byte_key);
    }

    EC_KEY_free(key);
    return 0;
}

Key Notes:

  • The hex string from BN_bn2hex() will match exactly the OCTET STRING value from your ASN.1 decoder (in your case, 61300E611C121ECBE7C2D49DA8FCD99571DF00296F51C3A9EC02DFF3063DBD3E).
  • The byte array uses big-endian order, which is the standard format for ECC private keys and works seamlessly with PKCS#11 imports later.
  • Always clean up allocated memory with OPENSSL_free() and EC_KEY_free() to avoid leaks.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 14:14:05