首先大體了解下X5519曲線算法和ECC橢圓曲線算法,ECC是Elliptic curve cryptography(橢圓曲線密碼學)的縮寫,嚴格的講X25519算法也是橢圓曲線算法的一種,但是和其他橢圓曲線算法不兼容(如secp256k1/secp354r1/secp521k1/prime256v1),所以OpenSSL最新版本雖然支持ECC算法,但是用法和其他橢圓曲線算法不同,相關情況可以參考:
- X25519(Curve25519)橢圓曲線參考資料:https://www.jianshu.com/p/5dba044f67b1
- OpenSSL在使用X25519時的小坑:https://blog.csdn.net/qmickecs/article/details/73193108
- 如何使用X25519派生共享秘鑰:https://github.com/project-everest/hacl-star/blob/master/tests/benchmark/bench_curve25519.cpp
問題在於我們使用時需要拿到X25519公鑰和私鑰的unsigned char*類型數據,但是OpenSSL在生成密鑰對和派生共享密鑰時都是用使用EVP_PKEY類型,對於一般的橢圓曲線算法,我們可以使用i2d_PublicKey/d21_PublicKey/i2d_PrivateKey/d21_PrivateKey進行兩種類型的轉換:
- EVP_PKEY from char buffer in x509 (PKCS7):https://stackoverflow.com/questions/2918923/evp-pkey-from-char-buffer-in-x509-pkcs7
但是結合如下鏈接以及查看OpenSSL源碼,發現這四個方法根本不適用EVP_PKEY_X25519類型,調用時直接返回-1。
- https://www.mail-archive.com/mailto:openssl-commits@openssl.org/msg20218.html
- https://github.com/openssl/openssl/pull/8168/commits/d3530f99473293a8fd5d309931e9021a7469deb2
從以下鏈接中可以獲取一些OpenSSL常用的轉換策略,但是仍然不適用於X25519:
- How does one access the raw ECDH public key, private key and params inside OpenSSL's EVP_PKEY structure? https://stackoverflow.com/questions/18155559/how-does-one-access-the-raw-ecdh-public-key-private-key-and-params-inside-opens
后來發現Stack Overflow的相關提問涉及到了ecx_get_priv_key/ecx_get_pub_key兩個函數,但是這兩個函數都是internal的,並沒有暴露給開發者,所以這條路也走不通
- How to use ecx get_priv/pub_key methods from openssl? https://stackoverflow.com/questions/59468839/how-to-use-ecx-get-priv-pub-key-methods-from-openssl
最后翻了下OpenSSL的Github issues,發現不少人遇到了這個問題:
- It's not possible to export the raw public key for X25519/Ed255919/X448/Ed448:https://github.com/openssl/openssl/issues/6259
- Add getters for raw private/public keys:https://github.com/openssl/openssl/pull/6394
從大家的討論中發現OpenSSL的commiter在1.1.1版本提供了EVP_PKEY_get_raw_private_key和EVP_PKEY_get_raw_public_key,經驗證可以使用: