Coder Social home page Coder Social logo

ocaml-x509's People

Contributors

dinosaure avatar hannesm avatar nightblues avatar paurkedal avatar pqwy avatar psafont avatar reynir avatar sg2342 avatar yallop avatar yomimono avatar zoggy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ocaml-x509's Issues

parsing pem from string

Hi,

I could not find a way to parse a certificate in pem format from a string (I want to access a certificate in a HTTP header, using apache proxy). I guess this is just a matter of adding some existing functions of x509_pem to X509 interface ?

`sexplib.syntax` in installed META

The current opam version of x509 installs a META which requires sexplib.syntax, and I can see the current _oasis lists it in BuildDepends. I don't think that was intentional, and it conflicts with deriving.syntax which is why I discovered it.

Remove version from opam file

It's better to remove version (and for what it's worth name) from opam files as it can break constraints when are pinning the dev versions.

See for instance the current state of mirage-dev:

[WARNING] A conflict was detected in your installation. This can be caused by updated
constraints in your installed packages:
  - x509 is not available because the package is pinned to https://github.com/mirleft/ocaml-x509.git, version 0.3.0.

feature: enhance Private_key module

since this library defines a Private_key.t type as a variant, functionality over these would be nice to have:

  • generate (taking a key_type)
  • key_type from and to string functions (for cmdliner usage) -- the existing key_type type could be retained and moved
  • sign (which does ECDSA encoding)
  • verify (in public_key, cares about decoding as well)

Error: Unbound type constructor RSA.priv

Fails to compile on 4.02.0 and 4.02.1 (haven't tried other versions).

$ opam install tls

#=== ERROR while installing x509.0.1.0 ========================================#
# opam-version 1.2.0
# os           linux
# command      ocaml setup.ml -build
# path         /home/edwin/.opam/4.02.1/build/x509.0.1.0
# compiler     4.02.1
# exit-code    1
# env-file     /home/edwin/.opam/4.02.1/build/x509.0.1.0/x509-22222-a00279.env
# stdout-file  /home/edwin/.opam/4.02.1/build/x509.0.1.0/x509-22222-a00279.out
# stderr-file  /home/edwin/.opam/4.02.1/build/x509.0.1.0/x509-22222-a00279.err
### stdout ###
# ...[truncated]
# /home/edwin/.opam/4.02.1/bin/ocamlfind ocamldep -package asn1-combinators -package cstruct -package nocrypto -syntax camlp4o -package sexplib.syntax -modules lib/list_ext.ml > lib/list_ext.ml.depends
# /home/edwin/.opam/4.02.1/bin/ocamlfind ocamldep -package asn1-combinators -package cstruct -package nocrypto -syntax camlp4o -package sexplib.syntax -modules lib/registry.ml > lib/registry.ml.depends
# /home/edwin/.opam/4.02.1/bin/ocamlfind ocamlc -c -g -package asn1-combinators -package cstruct -package nocrypto -syntax camlp4o -package sexplib.syntax -I lib -o lib/list_ext.cmo lib/list_ext.ml
# /home/edwin/.opam/4.02.1/bin/ocamlfind ocamlc -c -g -package asn1-combinators -package cstruct -package nocrypto -syntax camlp4o -package sexplib.syntax -I lib -o lib/registry.cmo lib/registry.ml
# /home/edwin/.opam/4.02.1/bin/ocamlfind ocamldep -package asn1-combinators -package cstruct -package nocrypto -syntax camlp4o -package sexplib.syntax -modules lib/certificate.mli > lib/certificate.mli.depends
# /home/edwin/.opam/4.02.1/bin/ocamlfind ocamlc -c -g -package asn1-combinators -package cstruct -package nocrypto -syntax camlp4o -package sexplib.syntax -I lib -o lib/asn_grammars.cmo lib/asn_grammars.ml
# + /home/edwin/.opam/4.02.1/bin/ocamlfind ocamlc -c -g -package asn1-combinators -package cstruct -package nocrypto -syntax camlp4o -package sexplib.syntax -I lib -o lib/asn_grammars.cmo lib/asn_grammars.ml
# File "lib/asn_grammars.ml", line 684, characters 58-66:
# Error: Unbound type constructor RSA.priv
# Command exited with code 2.
### stderr ###
# ...[truncated]
# File "setup.ml", line 2502, characters 6-24:
# Warning 3: deprecated: Lazy.lazy_from_fun
# Use Lazy.from_fun instead.
# File "setup.ml", line 247, characters 8-26:
# Warning 3: deprecated: String.set
# Use Bytes.set instead.
# File "setup.ml", line 2502, characters 6-24:
# Warning 3: deprecated: Lazy.lazy_from_fun
# Use Lazy.from_fun instead.
# E: Failure("Command ''/home/edwin/.opam/4.02.1/bin/ocamlbuild' lib/x509.cma lib/x509.cmxa lib/x509.a lib/x509.cmxs -tag debug' terminated with error code 10")

certificates with multiple common names

are not supported... maybe we need to construct an example and support it? or due to a very small deployed base, we can defer until there's a concrete use case for such a certificate!?

Cannot compile 0.1.0

I have an error when trying to compile the release 0.1.0:

File "lib/asn_grammars.ml", line 684, characters 58-66:
Error: Unbound type constructor RSA.priv

(Manually or via opam)

Cannot install due to dependency problem

I am trying to install via opam the tls package which depends on this (x509) package. I'm on up-to-date macOS with Ocaml 4.06.0. Unfortunately the installation fails due to dependency on asn1-combinators < 0.2.0.

$ opam install x509
The following dependencies couldn't be met:
  - x509 -> asn1-combinators < 0.2.0
  - x509 -> nocrypto < 0.5.2 -> sexplib < 113.01.00
  - x509 -> nocrypto < 0.5.2 -> ctypes < 0.4.0
Your request can't be satisfied:
  - asn1-combinators<0.2.0 is not available because your system doesn't comply with ocaml-version >= "4.01.0" & ocaml-version < "4.06.0".
  - ctypes<0.4.0 is not available because your system doesn't comply with ocaml-version >= "4.00.0" & ocaml-version < "4.03.0".
  - sexplib<113.01.00 is not available because your system doesn't comply with ocaml-version >= "4.02.1" & ocaml-version < "4.03".

No solution found, exiting

Furthermore, the previous version of asn1-combinators 0.1.3 cannot be installed due to compilation error.

Link to bug report for tls package: mirleft/ocaml-tls#370

Issues with the DN representation

The new Gmap-based Distinguished_name conflates DNs which should be treated as different, since it does not represent the ordering of RDNs. This can introduce security issues for applications relying on DN comparison for authorization. Also, DNs containing repeated attribute types cannot be represented. This is particularly an issue with DC, but I have seen other attribute types like O being repeated, as well.

RFC-5280 section 4.1.2.4 specifies the issuer DN as a sequence of RDNs where each RDN is a set of pairs of attribute type and value. So, the order of RDNs matter and an attribute type can be repeated both along a DN and also within an RDN set.

I could find the following DN representations in other OCaml packages:

  • The Ldap_types module from ldap defines a DN as a list of RDNs where an RDN is a single attribute type with multiple values. Not quite correct, but I haven't seen any counter-case.
  • The Netdn module from ocamlnet defines as a DN as a list of lists of pairs of attribute type and value, and makes a further restriction to only support DirectoryString values.
  • The asn1-combinators library has an example which uses essentially the same representation as ocamlnet, but makes a note that the attribute value "is ANY according to rfc5280."

Section 4.1.2.4 in the RFC says that "the type of the component AttributeValue is determined by the AttributeType; in general it will be a DirectoryString," so I think the Netdn restriction may be reasonable for X.509 usage. If we accept that, we can skip the polymorphism for the attribute values in the new representation.

I can help out with the implementation, but let's agree on the representation first.

API woes

a list of improvements of the API:

  • X509.Encoding.PEM.*.of_string should not throw Invalid_arg (at least those used for public keys)
  • use the result type instead (and also elsewhere)
  • provide pp (i.e. Formatter) instead of to_string
  • use Logs all over
  • get rid of X509.Validation.result type
  • on another note, the testsuite could be ported to alcotest instead of oUnit

Retrieving valid_from/valid_until from a certificate

Hello,

I currently need to get the dates defining when the certificate is valid. (to bind the functions in libnqsb-tls related to informations retrieval about the current peer)

It seems that those informations aren't currently exposed by the library, I had a chat with @hannesm that told me to open an issue, so here it is. :)

Expose X509.Certificate.compare

It would be pretty useful to have this, both to enable use in maps/sets, but also to be able to determine equality.

My use case is serializing a state to a file and performing sanity checking of this.

What I currently do is re-encoding both certificates to DER and comparing the result of that, but I guess that's a bit inefficient, and it's a bit silly to have to extend the X509.Certificate module everywhere I need to do this.

Incompatible with sexplib/ppx_sexp_conv v0.11.0

Related to mirleft/ocaml-nocrypto#143. After pinning nocrypto to git+https://github.com/gasche/ocaml-nocrypto.git#master-ocamlbuild-pack it is possible to install nocrypto and sexplib=v0.11.0 (currently they're marked as conflicting). However, x509 has the same problem and fails to build. In order to reproduce you need to apply the aforementioned pin and upgrade sexplib.

�[1mFile "�[1mlib/x509.ml", line 1�[0m�[0m:
�[1;31mError�[0m: The implementation lib/x509.ml
       does not match the interface lib/x509.cmi:
       ...
       In module Validation:
       Values do not match:
         val ca_error_of_sexp : Ppx_sexp_conv_lib.Sexp.t -> ca_error
       is not included in
         val ca_error_of_sexp : Sexplib.Sexp.t -> ca_error
       File "�[1mlib/x509.mli", line 510, characters 2-51�[0m: Expected declaration
       File "�[1mlib/x509_certificate.ml", line 340, characters 2-223�[0m:
         Actual declaration
Command exited with code 2.
pkg.ml: [ERROR] cmd ['ocamlbuild' '-use-ocamlfind' '-classic-display' '-j' '4' '-tag' 'debug'
     '-build-dir' '_build' 'opam' 'pkg/META' 'CHANGES.md' 'LICENSE.md'
     'README.md' 'lib/x509.a' 'lib/x509.cmxs' 'lib/x509.cmxa' 'lib/x509.cma'
     'lib/x509_crl_types.cmx' 'lib/x509_crl.cmx' 'lib/x509_ca.cmx'
     'lib/x509_pem.cmx' 'lib/x509_encoding.cmx' 'lib/x509_authenticator.cmx'
     'lib/x509_extension.cmx' 'lib/x509_request_types.cmx'
     'lib/x509_extension_types.cmx' 'lib/x509_types.cmx'
     'lib/x509_certificate.cmx' 'lib/asn_grammars.cmx' 'lib/registry.cmx'
     'lib/x509_common.cmx' 'lib/x509.cmx' 'lib/x509.cmi' 'lib/x509.mli']: exited with 10

cc @gasche

Related PR on nocrypto: mirleft/ocaml-nocrypto#144

feature: ed448 support

Hi,

Similarly to #137, ocaml-x509 does not support Ed448 (OID 1.3.101.113) at the moment. It's also mentioned in RFC8446, so opening this issue to track support.

Invalid_argument "X509: failed to parse certificate" when using X509.Encoding.Pem.Certificate.of_pem_cstruct1

Hi,

I'm trying to implement the server side of U2F in ocaml, and for that I have to verify a signature. I'm trying to import the pem certificate provided by the hardware token, but it seems like the library is failing to parse it. It looks like this (that's the example certificate from the yubico docs) :

-----BEGIN CERTIFICATE-----
MIICGzCCAQWgAwIBAgIEQMQSJTALBgkqhkiG9w0BAQswLjEsMCoGA1UEAxMjWXVi
aWNvIFUyRiBSb290IENBIFNlcmlhbCA0NTcyMDA2MzEwIBcNMTQwODAxMDAwMDAw
WhgPMjA1MDA5MDQwMDAwMDBaMCoxKDAmBgNVBAMMH1l1YmljbyBVMkYgRUUgU2Vy
aWFsIDEwODY1OTE1MjUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAStoklVeyhj
RHTxPqBxr6GzZx1cOmWerwd4zSGAdQuLd9jrnB8zMHh6jOQgDEjAx7X6db7iWGok
EpO42+jOPFrXoxIwEDAOBgorBgEEAYLECgEBBAAwCwYJKoZIhvcNAQELA4IBAQFY
NAaBBxBKeCyS2D2BQAkRkvFmYl5AgPHK2C4Bp873yl8D8MiiZVM2Mcb+caEa5ec4
5CFF4WeJpx2VbJ4/RGP1Rg7kUcyl+2LcU2aRWZ+3o92m4y4XJE5JEPwIVJJj+1bi
tgFi4GLEvHoxlKroIQbCr4f/OLsUwBK+QUvjhoNsou1CI3fFtJzgnOhDfHf/MAoj
zo7dmP/kyqSy01yrM5OFJ1jc0XcQU4ZgQaayQWWxdVclUbyZuckSwabYdxvCjL67
eDbtxHKI/0NeeCCaVntQ6dbqQxSzhvZ1gkUJNuWNuuJPQQyEn6rPsB71IyKNog5y
peVFaGrk1mk+zOirhMJe
-----END CERTIFICATE-----

It seems valid when I decode it with openssl, so I assume the problem must be what it contains.
Do you have by any chance an idea about what makes the parsing fail ? I've read in the doc some X503v3 extensions aren't supported, and that certificate seems to have some. Or is it the public key's format ?

Cstruct.of_string pemCert |> X509.Encoding.Pem.Certificate.of_pem_cstruct1

Why is Validation.trust_cert_fingerprint deprecated?

At the line below, it says that trust_cert_fingerprint is deprecated, and to use trust_key_fingerprint instead.

[@@ocaml.deprecated "Pin public keys (use trust_key_fingerprint) instead of certificates."]

However, this is very useful to have, since many tools (e.g. openssl x509 -fingerprint) do a fingerprint of the certificate instead of the key. Forcing key fingerprints makes this feature inaccessible.

mirage-crypto 0.8.9 breaks regression test

Excerpt from the tests:

> [FAIL]        Regression                                         11   sloppy private key parsing.


…

┌───────────────────────────────────────────────────────────────────────────────────────────────────┐
│ [FAIL]        Regression                                         11   sloppy private key parsing. │
└───────────────────────────────────────────────────────────────────────────────────────────────────┘
ASSERT private key gcloud, expected decoding error
FAIL private key gcloud, expected decoding error
Raised at file "src/alcotest-engine/test.ml", line 143, characters 20-48
Called from file "tests/regression.ml", line 132, characters 13-74
Called from file "src/alcotest-engine/core.ml", line 269, characters 17-23
Called from file "src/alcotest-engine/monad.ml", line 34, characters 31-35


Logs saved to `~/x509-v0.11.2/_build/default/tests/_build/_tests/X509 tests/Regression.011.output'.
 ──────────────────────────────────────────────────────────────────────────────

Full test results in `~/x509-v0.11.2/_build/default/tests/_build/_tests/X509 tests'.
1 failure! in 0.000s. 2195 tests run.

As far as I understanded 0.8.9 fixed not being able to handle gcloud keys properly, so it seems to me that x509 now holds wrong assumptions about mirage-crypto‽

Is it safe to ignore this test failure?

Negative RSA moduli from X509 parsing

When parsing some certificates using X509 I get a RSA pubkey with a negative modulus, but when parsing the same certificate with openssl I get a proper modulus.
I have the same issue whether I'm using X509.Encoding.parse on the DER encoded certificate or X509.Encoding.Pem.Cert.of_pem_cstruct1 on the PEM encoded certificate.

I had different negative moduli even though I can get the same from different certificates with totaly different keys.

For instance when parsing the following certificate :

-----BEGIN CERTIFICATE-----
MIICgjCCAeugAwIBAgIBADANBgkqhkiG9w0BAQUFADB8MSMwIQYDVQQDDBpNYXRy
aXhTU0wgU2FtcGxlIFNlcnZlciBDQTELMAkGA1UEBgwCVVMxCzAJBgNVBAgMAldB
MREwDwYDVQQHDAhCZWxsZXZ1ZTEZMBcGA1UECgwQUGVlcnNlYyBOZXR3b3JrczEN
MAsGA1UECwwEVGVzdDAeFw0wNjAzMTMwODEzMzRaFw0wNzAzMTMwODEzMzRaMH4x
JTAjBgNVBAMMHE1hdHJpeFNTTCBTYW1wbGUgU2VydmVyIENlcnQxCzAJBgNVBAYM
AlVTMQswCQYDVQQIDAJXQTERMA8GA1UEBwwIQmVsbGV2dWUxGTAXBgNVBAoMEFBl
ZXJTZWMgTmV0d29ya3MxDTALBgNVBAsMBFRlc3QwgZ4wDQYJKoZIhvcNAQEBBQAD
gYwAMIGIAoGArLJFx36VVxymSgNnepNJfNQ2Wh6RUoe3n6YakhtPWCXHRvGwNBr6
lOqt5bZkcsqM2FkUYMAdIV3DTvMXAVOUf9q0Ys27oIDny/0h2D8vVehjIScYrMrm
xPULuVuovFW4q+VMu+5vMp7U29j0zOHfn/xe687X7DjyaMd19eCcHiECAwEAAaMT
MBEwDwYDVR0TAQEBBAUwAwEBADANBgkqhkiG9w0BAQUFAAOBgQBX6R0aLW/agkug
2zl7kOxssCzi2l55Co6oGno+9t4Xk2IMVpIU/gas8RwnQRjFhw1M02yWobxYEh32
WRJdomY7VNB3m73VhMX909fP+m/d4shJNwB35oZn8JZPjmk9NB/ZGvxK6Zk0WttV
F/KVvu5//R80bStnBA4cAhP7FyUugg==
-----END CERTIFICATE-----

I get the following modulus using openssl :
121271520231624918542907720666513451111373723194411941835436037579884871354630882774466980950040637618229635985716165799223521502108721938227405738374601994957375171061467139291846177087270146140905134669029738067590090603243622428305533878351496216340646248930115097707562917176741486307355852155190932938273

and the following one using X509 :
-58497793254606672230022798412389022250423974699818715437994043577847804450870080358241496372366898402890477894155227558435268266705694684265441692264872129420392722363398345984456042513975947978547948283055267701248060079098840453168379232189331020822704261754471200532384328761738229997479504174433291198943

Do you have any idea where this might come from ?

feature: ed25519 support

I receive the following error from ca certs in the global trust store.

Fatal error: exception (Failure "Unknown algorithm 1.3.101.112")

This error is encountered in downstream ocaml projects whether or not we are actually interacting with the ed25519 based / signed certs.

Full support would be great, but politely ignoring the certs would be a solid work around. I'd imagine that there would also have to be work done in mirage-crypto. Let me know if there is anything I can do to help, thanks in adavance.

Serial number at 0 can not be decoded with #167

During my tests, I decided to generate certificates in the fly via this code:

module Ca = struct
  open Rresult

  let prefix =
    X509.Distinguished_name.
      [ Relative_distinguished_name.singleton (CN "Fuzzer") ]

  let cacert_dn =
    X509.Distinguished_name.(
      prefix
      @ [ Relative_distinguished_name.singleton (CN "Ephemeral CA for fuzzer") ])

  let cacert_lifetime = Ptime.Span.v (365, 0L)
  let cacert_serial_number = Z.zero

  let make domain_name seed =
    Domain_name.of_string domain_name >>= Domain_name.host
    >>= fun domain_name ->
    let private_key =
      let seed = Cstruct.of_string (Base64.decode_exn ~pad:false seed) in
      let g = Mirage_crypto_rng.(create ~seed (module Fortuna)) in
      Mirage_crypto_pk.Rsa.generate ~g ~bits:2048 ()
    in
    let valid_from = Ptime.v (Ptime_clock.now_d_ps ()) in
    Ptime.add_span valid_from cacert_lifetime
    |> Option.to_result ~none:(R.msgf "End time out of range")
    >>= fun valid_until ->
    X509.Signing_request.create cacert_dn (`RSA private_key) >>= fun ca_csr ->
    let extensions =
      let open X509.Extension in
      let key_id =
        X509.Public_key.id X509.Signing_request.((info ca_csr).public_key)
      in
      let authority_key_id =
        ( Some key_id,
          X509.General_name.(singleton Directory [ cacert_dn ]),
          Some cacert_serial_number )
      in
      empty
      |> add Subject_alt_name
           ( true,
             X509.General_name.(
               singleton DNS [ Domain_name.to_string domain_name ]) )
      |> add Basic_constraints (true, (false, None))
      |> add Key_usage
           (true, [ `Digital_signature; `Content_commitment; `Key_encipherment ])
      |> add Subject_key_id (false, key_id)
      |> add Authority_key_id (false, authority_key_id)
    in
    X509.Signing_request.sign ~valid_from ~valid_until ~extensions
      ~serial:cacert_serial_number ca_csr (`RSA private_key) cacert_dn
    |> R.reword_error (R.msgf "%a" X509.Validation.pp_signature_error)
    >>= fun certificate ->
    let fingerprint = X509.Certificate.fingerprint `SHA256 certificate in
    let time () = Some (Ptime_clock.now ()) in
    let authenticator =
      X509.Authenticator.server_cert_fingerprint ~time ~hash:`SHA256
        ~fingerprint
    in
    Ok (certificate, `RSA private_key, authenticator)
end

let seed = Base64.encode_exn "foo"

let () =
  Mirage_crypto_rng_unix.initialize (module Mirage_crypto_rng.Fortuna);
  let cert, _pk, _authenticator = Result.get_ok (Ca.make "foo.bar" seed) in
  match X509.Certificate.(decode_der (encode_der cert)) with
  | Ok _ -> ()
  | Error (`Msg msg) -> failwith msg

You can compile this code with:

$ ocamlfind opt -linkpkg -package digestif.c,mirage-crypto-rng.unix,x509,rresult,ptime.clock.os main.ml
$ ./a.out
$ echo $?
0

Since I tried to move to the repository which contains all required packages where Cstruct was remove, I noticed an error about X509.Certificate.decode_der. If we switch to no-cstruct and install x509.1.0.0~beta, we must update the code with this patch:

--- a.ml	2024-05-03 18:20:39.793393316 +0200
+++ b.ml	2024-05-03 18:21:03.681581905 +0200
@@ -17,7 +17,7 @@
     Domain_name.of_string domain_name >>= Domain_name.host
     >>= fun domain_name ->
     let private_key =
-      let seed = Cstruct.of_string (Base64.decode_exn ~pad:false seed) in
+      let seed = Base64.decode_exn ~pad:false seed in
       let g = Mirage_crypto_rng.(create ~seed (module Fortuna)) in
       Mirage_crypto_pk.Rsa.generate ~g ~bits:2048 ()
     in

And if we recompile the project, we got an error:

$ opam remote add no-cstruct https://github.com/robur-coop/no-cstruct.git
$ opam update
$ opam install x509.1.0.0~beta randomconv.0.2.0 mirage-crypto.1.0.0~beta mirage-crypto-rng.1.0.0~beta mirage-crypto-ec.1.0.0~beta mirage-crypto-pk.1.0.0~beta eqaf.1.0.0~beta pbkdf.2.0.0~beta hkdf.2.0.0~beta asn1-combinators.0.3.0
$ camlfind opt -linkpkg -package digestif.c,mirage-crypto-rng.unix,x509,rresult,ptime.clock.os main.ml
$ ./a.out
Fatal error: exception Failure("INTEGER: length 0")

If we set the cacert_serial_number to Z.one, everything works.

countryName is UTF8STRING when making a CSR

I made a CSR using ocaml-x509, and it wasn't accepted by openssl as country name "DK" is not the same as country name "DK". After being a bit puzzled by this error message I found out that ocaml-x509 encoded countryName as UTF8STRING while openssl generates and seemingly expects PrintableString.

[Public_key.verify]'s ECDSA evaluation mishandles long digests

(caveat emptor: I am not a cryptographer. I just read a wikipedia article)

There's a deviation in behavior between ocaml-x509 and other tools that verify x509 certificates, like OpenSSL or Chrome. Specifically, ocaml-x509 doesn't properly evaluate public key verification iff the hash function produces a digest longer than the length of the group order. I've observed an issue with a P-256 key (group order length '32') used with ECDSA_SHA384 (hash function digest length '48') around this code:

let* d = hashed hash data in
let* s = ecdsa_of_cs signature in
ok_if_true
(match key with
| `P224 key -> P224.Dsa.verify ~key s d
| `P256 key -> P256.Dsa.verify ~key s d
| `P384 key -> P384.Dsa.verify ~key s d
| `P521 key -> P521.Dsa.verify ~key s d)

[d] ends up being 48 bytes long when passed to [P256.Dsa.verify], which causes the function to silently fail with a [Message_too_long] exception. This is expected / correct / documented in the MLI:

https://github.com/mirage/mirage-crypto/blob/e60bbcbd5d3e0aebe4aadd2663e6cec6c3f9a38e/ec/mirage_crypto_ec.mli#L115-L119
val verify : key:pub -> Cstruct.t * Cstruct.t -> Cstruct.t -> bool (** [verify ~key (r, s) digest] verifies the signature [r, s] on the message [digest] with the public [key]. The return value is [true] if verification was successful, [false] otherwise. If the message has more bits than the group order, the result is false. *)

From wikipedia:

After that, Bob follows these steps:

  1. Verify that r and s are integers in [1,n-1]. If not, the signature is invalid.
  2. Calculate e={HASH}(m), where HASH is the same function used in the signature generation.
  3. Let z be the L_{n} leftmost bits of e.

I think Step 3 is missed here. I fixed this in a test environment by applying [Cstruct.take ~max:32] to [d] before passing it to the verify function [P256.Dsa.verify]. That should probably be baked into the logic for all four [key] cases, with [max] set to the appropriate [byte_length] (e.g. https://github.com/mirage/mirage-crypto/blob/e60bbcbd5d3e0aebe4aadd2663e6cec6c3f9a38e/ec/mirage_crypto_ec.ml#L738).

I'll offer the extra context that this isn't generally considered a best practice by (at least) Mozilla. See Section 5.1.2 of their policy where they claim that P-384 should be used with ECDSA_SHA384 to avoid these length mismatch issues. However, it is technically allowed (rather, not disallowed) by the Baseline Requirements (Section 6.1.5) various Certificate Authorities agree upon and should probably be supported by x509 libraries like ocaml-x509.

This truncation step is also a requirement when signing. I haven't verified this myself, but having spot checked the implementation of [Private_key.sign], it may be the case that this bug exists there as well.

Add support for name constraints

I don't have time to write the OCaml code for this, but I've already written the code to do this in both C++ for mozilla::pkix and libwebpki. The mozilla::pkix code is in pkixnames.cpp and the libwebpki code is in name.rs. Feel free to steal my code if it helps you. The libwebpki code is probably easier to copy because it avoids implementing CN-IDs and because it avoids implementing rfc822Name constraints. However, the mozilla::pkix code has actually been tested in real life in Firefox. Also, feel free to email me @ [email protected] if licensing or non-technical factors are an issue.

How to access some parts of a certificate

Hello,

Given a certificate (X509.t value), I want to retrieve the UID field of the Subject Alternative Name extension. I can't find functions to do so. Am I missing something ?

Mozilla PKIX guidelines

from: https://wiki.mozilla.org/SecurityEngineering/mozpkix-testing#Behavior_Changes

while they require basicConstraint=TRUE for CA certificates and not being present for server certificates (which we also do) - they also disallow X.509v1 and v2 certificates (apart from for trust anchors). This breaks most likely lots of self-signed certificates (deployed for mail servers etc) - but we might want to adapt to their behaviour. (Also, they disallow some outdated Netscape extensions)

Certificate verification allows dangerous algorithms

Hi,

Verification of a certificate chain does not check the signature algorithms themselves. At the moment, it should at least reject MD5 and SHA1 certificates. This is not a theoretical attack, there are SHA1 collisions, and it's possible to craft colliding MD5 certificates. As such, there's not much value in a valid signature based on these algorithms.

Browser vendors adopted an interesting strategy to sunset SHA1 (trusting them depending on when the certificate was issued), but that was several years ago - that is not necessary in 2019.

Thanks!

Add hostnames: csr -> string list for obtaining list of domains of a csr.

Dear brothers and sisters,

I am using x509 to implement the ACME protocol in ocaml <github.com/mmaker/ocaml-acme>.
This means that I have to deal with certificate signing requests, and for every domain listed in the request provide a proof to the CA that that domain is indeed owned by the used.
As a more eloquent example of this, take a look at
https://github.com/diafygi/acme-tiny/blob/master/acme_tiny.py#L65-75.
Later, at line 95 you can see that the client attempts to validate every domain in the signing request.

Currently I am asking the user the domain to validate as an extra argument, but all the information is already in the csr. I just cannot get it. I would be nice if X509 had implemented such a feature.

improve API (make it harder to use wrong)

as discussed with @emillon

  • remove Authenticator.null
  • make Authenticator.t abstract (and provide a constructor) <- more easily discover Authenticator.t uses
  • use time:(unit -> Ptime.t option) ((a) being explicit about time - (b) rename time to something more sensible - (c) also use a function to avoid the timestamp used at Authenticator creation time vs actual authentication)
  • use host:[`host] Domain_name.t option as well

accept out-of-order certificate chains

according to http://www.ietf.org/mail-archive/web/tls/current/msg16183.html and https://bugzilla.mozilla.org/show_bug.cgi?id=619445#c1 deployed systems send out-of-order chains.

additionally, due to cross-certification and stronger policies, verification should succeed once a certificate is signed by one in the trust store (no need to walk over the entire chain; depending on policy, such as 'no md5', there might be several paths which need to be explored).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.