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

PHP实现椭圆曲线DER私钥转PEM格式无效问题排查

prime256v1椭圆曲线VAPID密钥DER转PEM故障排查

密钥生成方式

参考web-push-php文档中VAPID认证章节的方法生成prime256v1椭圆曲线测试密钥对,使用的openssl命令如下:

openssl ecparam -name prime256v1 -genkey -noout -out vapid_private.pem
openssl ec -in vapid_private.pem -pubout -out vapid_public.pem
openssl ec -in vapid_private.pem -pubout -outform DER | tail -c 65 | base64 | tr -d '=' | tr '/+' '_-' > vapid_public.der
openssl ec -in vapid_private.pem -outform DER | tail -c +8 | head -c 32 | base64 | tr -d '=' | tr '/+' '_-' > vapid_private.der

生成的密钥文件内容

  • vapid_private.pem(PEM格式私钥):
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEICBP2ZDHFWjIfnJXDCXFMIQIXRwQofx531ikc2R3RK+qoAoGCCqGSM49
AwEHoUQDQgAEtHLtsp1L1Jaqj/IEueEvp9yvG3wg1POAlzEf77NsM9qTMFBQiBPj
Bu8tzN5lLXnjKMy4I+AATyOI7Kz2C8RVWg==
-----END EC PRIVATE KEY-----
  • vapid_public.pem(PEM格式公钥):
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEtHLtsp1L1Jaqj/IEueEvp9yvG3wg
1POAlzEf77NsM9qTMFBQiBPjBu8tzN5lLXnjKMy4I+AATyOI7Kz2C8RVWg==
-----END PUBLIC KEY-----
  • vapid_private.der(URL安全Base64编码raw DER私钥):
IE_ZkMcVaMh-clcMJcUwhAhdHBCh_HnfWKRzZHdEr6o
  • vapid_public.der(URL安全Base64编码raw DER公钥):
BLRy7bKdS9SWqo_yBLnhL6fcrxt8INTzgJcxH--zbDPakzBQUIgT4wbvLczeZS154yjMuCPgAE8jiOys9gvEVVo

故障描述

编写密钥转换类处理格式转换,目前4类转换场景中有3类可正常运行,唯独DER格式私钥转PEM格式的功能始终失效。当前精简版转换函数(已剥离错误处理逻辑)如下:

function convertECPrivateKeyFromDERtoPEM(string $der, string $passphrase = null): string
{
    $fullDer = "\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00" . self::base64_decode_url($der);
    return "-----BEGIN EC PRIVATE KEY-----\n" . chunk_split(base64_encode($fullDer), 64, "\n") . "-----END EC PRIVATE KEY-----";
}

拼接ASN.1前缀再封装PEM头尾的方案在公钥转换场景下可正常运行(仅需替换对应的PEM头尾与ASN.1前缀),是此前其他开发者实现的公钥转换逻辑。在此基础上扩展私钥转换支持时,函数返回的类PEM结构内容无法被openssl_pkey_get_private()识别为合法椭圆曲线密钥。

现有方案调研结果

调研多个现有PHP加密库,均未找到可直接使用的方案:

  • simplito/elliptic-php:未提供PEM格式生成能力,需要基于库能力额外编写大量封装代码
  • mdanter/ecc:无法直接加载原始DER格式密钥,仍需手动拼接ASN.1头,和现有实现方案相比没有优势
  • web-token/jwt-framework:提供的JWKFactory::createFromKey()方法会优先尝试解析DER格式、失败后回退解析PEM格式,但传入DER私钥时会抛出InvalidArgumentException: Unable to load the key异常

使用Perl语言的Crypt::PK::ECC库可将同一份raw DER私钥正确转换为和原始openssl生成结果完全一致的PEM私钥,对应命令如下:

perl -E 'use Crypt::PK::ECC; use MIME::Base64;my $k = Crypt::PK::ECC->new->import_key_raw(MIME::Base64::decode_base64url("IE_ZkMcVaMh-clcMJcUwhAhdHBCh_HnfWKRzZHdEr6o"), "prime256v1"); say $k->export_key_pem("private_short")'

该结果证明转换需求完全可实现,但始终无法写出可正常运行的PHP实现。OpenSSL返回的错误信息如下:

error:0D07209B:asn1 encoding routines:ASN1_get_object:too long
error:0D068066:asn1 encoding routines:asn1_check_tlen:bad object header
error:0D07803A:asn1 encoding routines:asn1_item_embed_d2i:nested asn1 error
error:10092010:elliptic curve routines:d2i_ECPrivateKey:EC lib
error:100DE08E:elliptic curve routines:old_ec_priv_decode:decode error
error:0D07209B:asn1 encoding routines:ASN1_get_object:too long
error:0D068066:asn1 encoding routines:asn1_check_tlen:bad object header
error:0D07803A:asn1 encoding routines:asn1_item_embed_d2i:nested asn1 error
error:0907B00D:PEM routines:PEM_read_bio_PrivateKey:ASN1 lib

因对密码学相关的ASN.1编码、密钥结构知识了解不深,难以独立定位问题,需要可行的解决方案。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 16:33:39