-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PKCS #1 v1.5 #41
Comments
Currently Ironclad has PKCS1-v2.1, but not PKCS1-v1.5. |
Hey @glv2 , Been too busy at $WORK, and I wasn't able to get back to this one sooner. I've been reading through RFC 8017 yesterday and implemented the stuff I needed in order to verify a RSASSA-PKCS1-v1_5 signature. Using the code below I was able to verify the signature of an OpenSSH Certificate when the certificate was signed with an RSA private key. Please let me know if you think this would be useful to be added in Ironclad. Thanks! ;;;;
;;;; Data Conversion Primitives - RFC 8017, section 4
;;;;
(defun i2osp (n &key n-bits)
"Integer-to-Octet-String primitive. See RFC 8017, section 4.1"
(declare (type integer n))
(let ((n-bits (or n-bits (integer-length n))))
(ironclad:integer-to-octets n :n-bits n-bits)))
(defun os2ip (octet-vec)
"Octet-String-to-Integer primitive. See RFC 8017, section 4.2"
(ironclad:octets-to-integer octet-vec))
;;;;
;;;; Signature and verification primitives - RFC 8017, section 5.2
;;;;
(defun rsasp1 (priv-key message)
"RSA signature primitive. See RFC 8017, section 5.2.1"
(declare (type integer message))
(let ((n (ironclad:rsa-key-modulus priv-key))
(d (ironclad:rsa-key-exponent priv-key)))
(unless (<= 0 message (1- n))
(error "message representative out of range"))
(ironclad:expt-mod message d n)))
(defun rsavp1 (public-key signature)
"RSA verification primitive. See RFC 8017, section 5.2.2"
(declare (type integer signature))
(let ((n (ironclad:rsa-key-modulus public-key))
(e (ironclad:rsa-key-exponent public-key)))
(unless (<= 0 signature (1- n))
(error "signature representative out of range"))
(ironclad:expt-mod signature e n)))
;;;;
;;;; Encoding Methods for Signatures with Appendix
;;;;
(defparameter *emsa-pkcs1-v1_5-digest-info*
'(:md2 #(#x30 #x20 #x30 #x0c #x06 #x08 #x2a #x86 #x48 #x86 #xf7 #x0d #x02 #x02 #x05 #x00 #x04 #x10)
:md5 #(#x30 #x20 #x30 #x0c #x06 #x08 #x2a #x86 #x48 #x86 #xf7 #x0d #x02 #x05 #x05 #x00 #x04 #x10)
:sha1 #(#x30 #x21 #x30 #x09 #x06 #x05 #x2b #x0e #x03 #x02 #x1a #x05 #x00 #x04 #x14)
:sha256 #(#x30 #x31 #x30 #x0d #x06 #x09 #x60 #x86 #x48 #x01 #x65 #x03 #x04 #x02 #x01 #x05 #x00 #x04 #x20)
:sha384 #(#x30 #x41 #x30 #x0d #x06 #x09 #x60 #x86 #x48 #x01 #x65 #x03 #x04 #x02 #x02 #x05 #x00 #x04 #x30)
:sha512 #(#x30 #x51 #x30 #x0d #x06 #x09 #x60 #x86 #x48 #x01 #x65 #x03 #x04 #x02 #x03 #x05 #x00 #x04 #x40))
"DigestInfo DER encoding of the known hash functions. See RFC 8017, section 9.2, notes 1.")
(defun emsa-pkcs1-v1_5-encode (digest-spec message em-len)
"EMSA-PKCS1-v1_5 encoding method. See RFC 8017, section 9.2"
(unless (member digest-spec *emsa-pkcs1-v1_5-digest-info*)
(error "unsupported digest spec"))
(let* ((algorithm-identifier (getf *emsa-pkcs1-v1_5-digest-info* digest-spec))
(h (ironclad:digest-sequence digest-spec message)) ;; Step 1
(tt (concatenate '(vector (unsigned-byte 8) *) ;; Step 2
algorithm-identifier
h))
(tt-len (length tt)))
(when (< em-len (+ tt-len 11)) ;; Step 3
(error "intended encoded message length too short"))
(let* ((ps (make-array (- em-len tt-len 3) ;; Step 4
:element-type '(unsigned-byte 8)
:initial-element #xff)))
(when (< (length ps) 8)
(error "PS length should be at least 8 octets"))
;; Step 5 and 6
(concatenate '(vector (unsigned-byte 8) *)
#(#x00 #x01) ps #(#x00) tt))))
;;;;
;;;; Signature Scheme with Appendix - RFC 8017, section 8
;;;;
(defun rsassa-pkcs1-v1_5-sign (priv-key message digest-spec)
"RSASSA-PKCS1-v1_5 signature generation. See RFC 8017, section 8.2.1"
(let* ((n (ironclad:rsa-key-modulus priv-key))
(k (ceiling (integer-length n) 8))
(em (emsa-pkcs1-v1_5-encode digest-spec message k)) ;; Step 1
(m (os2ip em)) ;; Step 2a
(s (rsasp1 priv-key m))) ;; Step 2b
;; Step 2c and 3
(i2osp s :n-bits (* 8 k))))
(defun rsassa-pkcs1-v1_5-verify (public-key message signature digest-spec)
"RSASSA-PKCS1-v1_5 signature verification. See RFC 8017, section 8.2.2"
(let* ((n (ironclad:rsa-key-modulus public-key))
(k (ceiling (integer-length n) 8)))
;; Step 1
(unless (= k (length signature))
(error "invalid signature"))
(let* ((s (os2ip signature)) ;; Step 2a
(m (rsavp1 public-key s)) ;; Step 2b
(em (i2osp m :n-bits (* 8 k))) ;; Step 2c
(em-prime (emsa-pkcs1-v1_5-encode digest-spec message k))) ;; Step 3
;; Step 4
(equalp em em-prime))))
|
As Ironclad usually includes basic cryptographic primitives and not complete protocols, maybe we could add functions for the raw PKCS1 v1.5 encoding, encryption, decryption, signature and verification as it is done for OAEP and PSS (see src/public-key/pkcs1.lisp and src/public-key/rsa.lisp). Then the complete protocol with the DER encoded info could go into a new library called rsa-pkcs1, crypto-rfc8017 or something like that. |
Hi,
I have a signature and a message I want to validate using the RSA public key of a CA. In order to verify the message I need to use
PKCS #1 v1.5
.Is this supported in Ironclad, as I wasn't able to find it?
Thanks!
The text was updated successfully, but these errors were encountered: