OpenSSL Ed25519 与钠 php 不起作用

问题描述 投票:0回答:1

我尝试使用 PHP 7.4 Sodium 加密消息。

此功能:

sodium_crypto_box_seal('Hello World', $pemPublicKey);

返回错误:

“参数 2 必须为 CRYPTO_BOX_PUBLICKEYBYTES 长。”

$pemPublicKey 存储在文件 public33.pem 中,我像这样检索它:

 $pemPublicKey = file_get_contents(PEM_FILES_PATH . '/public33.pem');  
 $pemPublicKey = str_replace('-----BEGIN PUBLIC KEY-----', '', $pemPublicKey);
 $pemPublicKey = str_replace('-----END PUBLIC KEY-----', '', $pemPublicKey);
 $pemPublicKey = trim($pemPublicKey);
 $pemPublicKey = base64_decode($pemPublicKey);
 $enc = sodium_crypto_box_seal('Hello World', $pemPublicKey);

public33.pem 文件的内容是:

-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEA5d3iW1eV66LJbBub+hrZinr2Uky6RfqYG3VNxQnCl4U=
-----END PUBLIC KEY-----

我已经检查过,文件内容读取正确。 主密钥和公钥文件是这样创建的:

1. openssl genpkey -algorithm Ed25519 -out private33.bin
2. openssl pkey -in private33.pem -pubout -out public33.pem 

我被困住了,不知道该往哪里看。

cryptography
1个回答
0
投票

sodium_crypto_box_seal()
不需要 X.509/SPKI 格式的 PEM 公钥,而是原始的 32 字节公钥。您可以从 PEM 公钥中提取该密钥作为 Base64 解码主体的最后 32 个字节。

但是,您为

sodium_crypto_box_seal()
使用了错误类型的密钥对。您不需要 Ed25519 密钥对,而是 X25519 密钥对,因此您必须调整 OpenSSL 语句并生成新密钥:

openssl genpkey -algorithm X25519 -out private33.pem
...

PHP代码:

<?php
// Encryption
$pemSPKI = "-----BEGIN PUBLIC KEY-----
MCowBQYDK2VuAyEACK2b1mIhIdgont5UdtboDiHQYMJlrJKjCBaWk1LbFS8=
-----END PUBLIC KEY-----";
$pemSPKI = str_replace('-----BEGIN PUBLIC KEY-----', '', $pemSPKI);
$pemSPKI = str_replace('-----END PUBLIC KEY-----', '', $pemSPKI);
$pemSPKI = trim($pemSPKI);
$derSPKI = base64_decode($pemSPKI);
$rawPublic = substr($derSPKI, -32);                         // Fix: extract raw public X25519 key
$ct = sodium_crypto_box_seal('Hello World', $rawPublic);
print("ciphertext: " .  bin2hex($ct) . PHP_EOL);

// Decryption
$pemPkcs8 = "-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VuBCIEIFAjP8X4es8alPOfr7ew/JKePnBvA49xiz2R0ZxO5wBZ
-----END PRIVATE KEY-----"; 
$pemPkcs8 = str_replace('-----BEGIN PRIVATE KEY-----', '', $pemPkcs8);
$pemPkcs8 = str_replace('-----END PRIVATE KEY-----', '', $pemPkcs8);
$pemPkcs8 = trim($pemPkcs8);
$derPkcs8 = base64_decode($pemPkcs8);
$rawPrivate = substr($derPkcs8, -32);
$dt = sodium_crypto_box_seal_open($ct, $rawPrivate . $rawPublic);
print("decrypted:  " .  $dt . PHP_EOL);
?>
© www.soinside.com 2019 - 2024. All rights reserved.