Невозможно извлечь информацию из файла p12 в Common Lisp
Я пытаюсь извлечь информацию из сертификата клиента, зашифрованного в PKCS#12 в Common Lisp.
Я попытался с помощью следующих шагов:
- Загрузите данный файл p12 на
BIO
сd2i_PKCS12_bio
- Подтвердите пароль с помощью
PKCS12_verify_mac
- Разобрать файл с помощью
PKCS12_parse
Вот фактический код CFFI:
(defun load-pkcs12 (file &optional passphrase)
(openssl-add-all-digests)
(pkcs12-pbe-add)
;; 1. Load the given p12 file
(let ((content (slurp-file file)))
(cffi:with-pointer-to-vector-data (data-sap content)
(let* ((bio (bio-new-mem-buf data-sap (length content)))
(p12 (d2i-pkcs12-bio bio (cffi:null-pointer)))
(pkey (evp-pkey-new))
(cert (x509-new)))
(unwind-protect
(progn
;; 2. Verify the passphrase
(let ((res (pkcs12-verify-mac p12 (or passphrase (cffi:null-pointer)) (length passphrase))))
(when (zerop res)
(error (format nil "Error while verifying mac~%~A" (get-errors)))))
;; 3. Parse the file
(cffi:with-foreign-objects ((*pkey :pointer)
(*cert :pointer))
(setf (cffi:mem-ref *pkey :pointer) pkey
(cffi:mem-ref *cert :pointer) cert)
(let ((res
(pkcs12-parse p12
(or passphrase (cffi:null-pointer))
*pkey
*cert
(cffi:null-pointer))))
(when (zerop res)
(error "Error in pkcs12-parse~%~A" (get-errors)))))
(pkcs12-free p12)
;; 4. Show the result
(let ((bio (cl+ssl::bio-new (bio-s-mem))))
(unwind-protect
(progn
(x509-print-ex bio cert 0 0)
(bio-to-string bio))
(bio-free bio))))
(evp-pkey-free pkey)
(x509-free cert))))))
Тем не менее, результат от X509_print_ex
всегда бессмысленно
Certificate:
Data:
Version: 1 (0x0)
Serial Number: 0 (0x0)
Signature Algorithm: itu-t
Issuer:
Validity
Not Before: Bad time value
Это выглядит хорошо, когда я попробовал это с openssl
команда, поэтому я предполагаю, что файл p12 в порядке:
$ openssl pkcs12 -in sslcert.p12 -clcerts -nokeys
Enter Import Password: <input passphrase>
MAC verified OK
Bag Attributes
localKeyID: 31 0E 0D 31 05 8D 20 13 BA B3 81 85 57 AD 28 52 9F D0 19 BE
subject=/C=JP/ST=Tokyo/L=Minato/O=<company>/OU=Development/CN=<user>/emailAddress=admin@example.co.jp
issuer=/C=JP/ST=Tokyo/O=<company>/OU=Development/CN=SuperUser Intermediate CA/emailAddress=admin@example.co.jp
-----BEGIN CERTIFICATE-----
...PEM-encoded certificate...
-----END CERTIFICATE-----
Полные фрагменты пантомимы на суть. Основная функция load-pkcs12
в нижней части файла.
(load-pkcs12 #P"/path/to/sslcert.p12" "password")
Кто-нибудь может здесь помочь?
Что я сослался
1 ответ
Я думаю, что проблема с этим кодом заключается в распределенииpkey
иcert
как пустые объекты сevp-pkey-new
иx509-new
соответственно.
Следующий код выполняет нечто подобное; обратите внимание на использованиеcffi:foreign-alloc
иcffi:mem-ref
.
(define-condition ssl-pkcs12-error (error)
((texto :initarg :texto :initform nil :reader ssl-pkcs12-error-texto)))
(defun ssl-pkcs12-descifra (archivo contra salida)
(let ((fp (cffi:foreign-funcall "fopen" :string archivo :string "rb" :pointer)))
(when (cffi:null-pointer-p fp)
(error 'ssl-pkcs12-error :texto (format nil "No pudo abrise el archivo: ~s" archivo)))
(let ((p12 (d2i-pkcs12-fp fp (cffi:null-pointer))))
(cffi:foreign-funcall "fclose" :pointer fp :int)
(when (cffi:null-pointer-p p12)
(error 'ssl-pkcs12-error :texto "Error leyendo el archivo PKCS#12"))
(let* ((pkey (cffi:foreign-alloc :pointer))
(cert (cffi:foreign-alloc :pointer))
(res (pkcs12-parse p12 contra pkey cert (cffi:null-pointer))))
(pkcs12-free p12)
(when (zerop res)
(error 'ssl-pkcs12-error :texto "Error interpretando el archivo PKCS#12"))
(let ((fp (cffi:foreign-funcall "fopen" :string salida :string "w" :pointer)))
(when (cffi:null-pointer-p fp)
(error 'ssl-pkcs12-error
:texto (format nil "No pudo crearse el archivo: ~s" salida)))
(unless (cffi:null-pointer-p (cffi:mem-ref pkey :pointer))
(pem-write-privatekey fp (cffi:mem-ref pkey :pointer)
(cffi:null-pointer) (cffi:null-pointer)
0 (cffi:null-pointer) (cffi:null-pointer))
(evp-pkey-free (cffi:mem-ref pkey :pointer)))
(unless (null-pointer-p (cffi:mem-ref cert :pointer))
(pem-write-x509 fp (cffi:mem-ref cert :pointer))
(x509-free (cffi:mem-ref cert :pointer)))
(cffi:foreign-free pkey)
(cffi:foreign-free cert)
(cffi:foreign-funcall "fclose" :pointer fp :int))))))