anchor.diff:         ;; -- specifiedCurve  SpecifiedECDomain
          ;;      }
          (unless (or (eql (first (second public-key-algorithm)) :null)
  -		   (eql (first (second public-key-algorithm)) :oid))
  -	 (error 'x509-decoding-error
  -		:text "ECParameters for id-ecPublicKey should be either NULL or OID"))
  +                   (eql (first (second public-key-algorithm)) :oid))
  +         (error 'x509-decoding-error
  +                :text "ECParameters for id-ecPublicKey should be either NULL or OID"))
          (let ((named-curve (second (second public-key-algorithm))))
  -	 (setf (getf params :named-curve)
  -	       (cond
  -		 ((equal named-curve '(1 2 840 10045 3 1 1)) :secp192r1)
  -		 ((equal named-curve '(1 2 840 10045 3 1 7)) :secp256r1)
  -		 ((equal named-curve '(1 3 132 0 1)) :sect163k1)
  -		 ((equal named-curve '(1 3 132 0 15)) :sect163r2)
  -		 ((equal named-curve '(1 3 132 0 16)) :sect283k1)
  -		 ((equal named-curve '(1 3 132 0 17)) :sect283r1)
  -		 ((equal named-curve '(1 3 132 0 26)) :sect233k1)
  -		 ((equal named-curve '(1 3 132 0 27)) :sect233r1)
  -		 ((equal named-curve '(1 3 132 0 33)) :secp224r1)
  -		 ((equal named-curve '(1 3 132 0 34)) :secp384r1)
  -		 ((equal named-curve '(1 3 132 0 35)) :secp521r1)
  -		 ((equal named-curve '(1 3 132 0 36)) :sect409k1)
  -		 ((equal named-curve '(1 3 132 0 37)) :sect409r1)
  -		 ((equal named-curve '(1 3 132 0 38)) :sect571k1)
  -		 ((equal named-curve '(1 3 132 0 39)) :sect571r1)
  -		 (t
  -		  (error 'x509-decoding-error
  -			 :text "Unknown or unsupported EC named curve"))))))
  +         (setf (getf params :named-curve)
  +               (cond
  +                 ((equal named-curve '(1 2 840 10045 3 1 1)) :secp192r1)
  +                 ((equal named-curve '(1 2 840 10045 3 1 7)) :secp256r1)
  +                 ((equal named-curve '(1 3 132 0 1)) :sect163k1)
  +                 ((equal named-curve '(1 3 132 0 15)) :sect163r2)
  +                 ((equal named-curve '(1 3 132 0 16)) :sect283k1)
  +                 ((equal named-curve '(1 3 132 0 17)) :sect283r1)
  +                 ((equal named-curve '(1 3 132 0 26)) :sect233k1)
  +                 ((equal named-curve '(1 3 132 0 27)) :sect233r1)
  +                 ((equal named-curve '(1 3 132 0 33)) :secp224r1)
  +                 ((equal named-curve '(1 3 132 0 34)) :secp384r1)
  +                 ((equal named-curve '(1 3 132 0 35)) :secp521r1)
  +                 ((equal named-curve '(1 3 132 0 36)) :sect409k1)
  +                 ((equal named-curve '(1 3 132 0 37)) :sect409r1)
  +                 ((equal named-curve '(1 3 132 0 38)) :sect571k1)
  +                 ((equal named-curve '(1 3 132 0 39)) :sect571r1)
  +                 (t
  +                  (error 'x509-decoding-error
  +                         :text "Unknown or unsupported EC named curve"))))))
         ((equal '(1 3 132 1 12) pka)
          (setf algorithm :ecdh))
         (t
          (error 'x509-decoding-error
  -	      :text "Unrecognized or unsupported public key algorithm")))
  +              :text "Unrecognized or unsupported public key algorithm")))
       (cons algorithm params)))
   
   (defun parse-pub-key (ov algorithm)
  
positive.code:     (unless (every (lambda (arg) (eql (first arg) :sequence)) extensions)
        (error 'x509-decoding-error :text "Extensions should be DER sequences"))
      (setf extensions
  	  (loop for ext in extensions collecting (second ext)))
      (unless (every (lambda (arg)
  		     (or
  		      (and (= 3 (length arg))
  			   (eql (first (first arg)) :oid)
  			   (eql (first (second arg)) :boolean)
  			   (eql (first (third arg)) :octet-string))
  		      (and (= 2 (length arg))
  			   (eql (first (first arg)) :oid)
  			   (eql (first (second arg)) :octet-string))))
  		   extensions)
        (error 'x509-decoding-error :text "Error parsing extensions"))
      (setf extensions (loop
  		       for ext in extensions
  		       collecting
  		       (if (= (length ext) 2)
  			   (destructuring-bind (extension-id extension-value) ext
  			     (list (second extension-id)
  				   nil
  				   (second extension-value)))
  			   (destructuring-bind (extension-id critical-p extension-value) ext
  			     (list (second extension-id)
  				   (second critical-p)
  				   (second extension-value))))))
      (loop
        for ext in extensions do
  	(destructuring-bind (extension-id critical-p extension-value) ext
  	  (cond
  	    ((equal extension-id '(2 5 29 35))
  	     (process-extension extension-bag critical-p
  				extension-value :authority-key-identifier))
  	    ((equal extension-id '(2 5 29 14))
  	     (process-extension extension-bag critical-p
  				extension-value :subject-key-identifier))
  	    ((equal extension-id '(2 5 29 15))
  	     (process-extension extension-bag critical-p
  				extension-value :key-usage))
  	    ((equal extension-id '(2 5 29 32))
  	     (process-extension extension-bag critical-p
  				extension-value :certificate-policies))
  	    ((equal extension-id '(2 5 29 33))
  	     (process-extension extension-bag critical-p
  				extension-value :policy-mappings))
  	    ((equal extension-id '(2 5 29 17))
  	     (process-extension extension-bag critical-p
  				extension-value :subject-alternative-name))
  	    ((equal extension-id '(2 5 29 18))
  	     (process-extension extension-bag critical-p
  				extension-value :issuer-alternative-name))
  	    ((equal extension-id '(2 5 29 19))
  	     (process-extension extension-bag critical-p
  				extension-value :basic-constraints))
  	    ((equal extension-id '(2 5 29 30))
  	     (process-extension extension-bag critical-p
  				extension-value :name-constraints))
  	    ((equal extension-id '(2 5 29 36))
  	     (process-extension extension-bag critical-p
  				extension-value :policy-constraints))
  	    ((equal extension-id '(2 5 29 37))
  	     (process-extension extension-bag critical-p
  				extension-value :extended-key-usage))
  	    ((equal extension-id '(2 5 29 31))
  	     (process-extension extension-bag critical-p
  				extension-value :crl-distribution-points))
  	    ((equal extension-id '(2 5 29 54))
  	     (process-extension extension-bag critical-p
  				extension-value :inhibit-anypolicy))
  	    ((equal extension-id '(2 5 29 46))
  	     (process-extension extension-bag critical-p
  				extension-value :freshest-crl))
  	    ((equal extension-id '(1 3 6 1 5 5 7 1 1))
  	     (process-extension extension-bag critical-p extension-value
  				:authority-information-access))
  	    ((equal extension-id '(1 3 6 1 5 5 7 1 11))
  	     (process-extension extension-bag critical-p
  				extension-value :subject-information-access))
  	    (t
  	     (when critical-p ;the extension is unknown and critical
  	       (error 'extension-bag-decoding-error
  		      :text "Encountered unknown critical extension"))))))
      extension-bag))
  
  (defmacro bind-tbs (tbs &body body)
    `(if (eql (first (first ,tbs)) 0)
         (destructuring-bind (version serial certificate-signature-algorithm
  			    issuer validity subject subject-public-key-info
  			    &optional extensions) ,tbs
  	 ,@body)
         (destructuring-bind (serial certificate-signature-algorithm
  			    issuer validity subject subject-public-key-info
  			    &optional extensions version) ,tbs
  	 ,@body)))
  
  (defun parse-tbs-certificate (tbs-certificate)
    ;; Remove obsolete UniqueIdentifier fields if present, we're not interested in them
    (setf tbs-certificate
  	(remove-if (lambda (el) (if (eql (first el) :bit-string) t)) tbs-certificate))
    (unless (<= 6 (length tbs-certificate) 8)
      (error 'x509-decoding-error
  	   :text "There must be 6|7|8 elements in tbs-certificate"))
    (bind-tbs
     tbs-certificate
     (make-instance
      'tbs-certificate
      :version
      (cond (version
  	   (unless (eql (first version) 0)
  	     (error 'x509-decoding-error
  		    :text "Version field should be explicitly tagged with type=0"))
  	   (let ((v (multiple-value-list (parse-der (second version)))))
  	     (unless (eql (first v) :integer)
  	       (error 'x509-decoding-error
  		      :text "Version field should be an ASN.1 integer"))
  	     (unless (<= 1 (second v) 2)
  	       (error 'x509-decoding-error :text "Version must be 2 or 3"))
  	     (1- (second v))))
  	  (t
  	   1))
      :serial
      (progn 
        (unless (eql (first serial) :integer)
  	(error 'x509-decoding-error :text "Serial field should be an ASN.1 integer"))
        (second serial))
      :signature
      (progn (unless (eql (first certificate-signature-algorithm) :sequence)
  	     (error 'x509-decoding-error
  		    :text "Signature algorithm field should be an ASN.1 sequence"))
  	   (multiple-value-bind (signature-algorithm digest-algorithm)
  	       (parse-signature-algorithm (second certificate-signature-algorithm))
  	     ;; (unless (and (eql (car (signature-algorithm x509)) signature-algorithm)
  	     ;; 		  (eql (cdr (signature-algorithm x509)) digest-algorithm))
  	     ;;   (error 'x509-decoding-error :text "Unexpected SignatureAlgorithm"))
  	     (cons signature-algorithm digest-algorithm)))
      :issuer
      (progn (unless (eql (first issuer) :sequence)
  	     (error 'x509-decoding-error
  		    :text "Signature algorithm field should begin with an OID"))
  	   (parse-directory-name (second issuer)))
      :validity
      (progn
        (unless (eql (first validity) :sequence)
  	(error 'x509-decoding-error :text "Validity field should be an ASN.1 sequence"))
        (setf validity (second validity))
        (loop for time in validity do
  	(unless (or (and (eql (first time) :utc-time)
  			 (= (length (second time)) 13)
  			 (every #'digit-char-p (subseq (second time) 0 12)))
  		    (and (eql (first time) :generalized-time)
  			 (= (length (second time)) 15)
  			 (every #'digit-char-p (subseq (second time) 0 14))))
  	  (error 'x509-decoding-error :text "Invalid encoding-validity field")))
        (let (dates)
  	(setf (getf dates :not-before)
  	      (asn-time-to-universal-time (second (first validity))))
  	(setf (getf dates :not-after)
  	      (asn-time-to-universal-time (second (second validity))))
  	dates))
      :subject
      (progn
        (unless (eql (first subject) :sequence)
  	(error 'x509-decoding-error
  	       :text "Signature algorithm field should begin with an OID"))
        (parse-directory-name (second subject)))
      :subject-pki
      (let (pk)
        (unless (eql (first subject-public-key-info) :sequence)
  	(error 'x509-decoding-error
  	       :text "SubjectPublicKeyInfo field should be an ASN.1 sequence"))
        (setf subject-public-key-info (second subject-public-key-info))
        (unless (and (= 2 (length subject-public-key-info))
  		   (eql (first (first subject-public-key-info)) :sequence)
  		   (eql (first (second subject-public-key-info)) :bit-string))
  	(error 'x509-decoding-error
  	       :text "Length or type mismatch in SubjectPublicKeyInfo field"))
        ;; AlgorithmIdentifier
        (setf (getf pk :algorithm-identifier)
  	    (parse-pka (second (first subject-public-key-info))))
        ;; subjectPublicKey
        (setf (getf pk :subject-public-key)
  	    (parse-pub-key (second (second subject-public-key-info))
  			   (car (getf pk :algorithm-identifier))))
        pk)
      :extensions (when extensions
  		  (process-extensions extensions)))))
  
  (defun x509-decode (octet-vector)
    "Deserialize an x509 certificate from an octet-vector"
    (let* ((x509 (make-instance 'x509v3-certificate :raw octet-vector :hash (ironclad:digest-sequence :sha3/224 octet-vector)))
  	 (certificate
  	   (multiple-value-bind (element-type contents)
  	       (parse-der octet-vector)
  	     (unless (eql element-type :sequence)
  	       (error 'x509-decoding-error
  		      :text "Expected ASN.1 sequence. Element: certificate"))
  	     contents)))
      (unless (= (length certificate) 3)
        (error 'x509-decoding-error "Invalid certificate"))
      (destructuring-bind (tbs-certificate signature-algorithm signature) certificate
        (unless (eql (first tbs-certificate) :sequence)
  	(error 'x509-decoding-error
  	       :text "Expected ASN.1 sequence. Element: tbs-certificate"))
        (unless (eql (first signature-algorithm) :sequence)
  	(error 'x509-decoding-error
  	       :text "Expected ASN.1 sequence. Element: signature-algorithm"))
        (unless (eql (first signature) :bit-string)
  	(error 'x509-decoding-error :text "Expected ASN.1 bit string. Element: signature"))
        ;; Certificate signature
        (setf (signature x509) (second signature))
        ;; Certificate signature algorithm
        (multiple-value-bind (signature-algorithm digest-algorithm)
  	  (parse-signature-algorithm (second signature-algorithm))
  	(setf (signature-algorithm x509)
  	      (cons signature-algorithm digest-algorithm)))
        ;; TBScertificate
        (setf (tbs-certificate x509)
  	    (parse-tbs-certificate (second tbs-certificate))))
      x509))
  
  (defun asn-time-to-universal-time (time-string)
  
negative.code:       ;; RSAPublicKey ::= SEQUENCE { modulus INTEGER, -- n publicExponent INTEGER -- e }
        (:rsa
         (let ((rsa-public-key (multiple-value-list
                                (parse-der ov :start 1))))
           (unless (eql (first rsa-public-key) :sequence)
             (error 'x509-decoding-error :text "The subjectPublicKeyInfo bit string should contain an ASN.1 sequence"))
           (setf rsa-public-key (second rsa-public-key))
           (loop for element in rsa-public-key do
             (unless (eql (first element) :integer)
               (error 'x509-decoding-error :text "Expected integers in PKI field.")))
           (setf (getf pub-key :modulus) (second (first rsa-public-key)))
           (setf (getf pub-key :public-exponent) (second (second rsa-public-key)))))
        ;; DSA
        (:dsa
         (let ((dsa-public-key (multiple-value-list
                                (parse-der ov :start 1))))
           (unless (eql (first dsa-public-key) :integer)
             (error 'x509-decoding-error :text "Expected a DSA public key; DSAPublicKey ::= INTEGER -- public key, Y"))
           (setf (getf pub-key :dsa-public-key) (second dsa-public-key))))
        ;; DH
        (:dh
         (let ((dh-public-value (multiple-value-list
                                 (parse-der ov :start 1))))
           (unless (eql (first dh-public-value) :integer)
             (error 'x509-decoding-error :text "Invalid encoding of subjectPublicKeyInfo"))
           (setf (getf pub-key :dh-Y) (second dh-public-value)))))
      pub-key))
  
  (defun parse-signature-algorithm (sig)
  