pimeys / rust-web-push

A Web Push library for Rust
Apache License 2.0
113 stars 21 forks source link

How to supply private and public in Vapid key format? #35

Closed Hugo-Persson closed 1 year ago

Hugo-Persson commented 1 year ago

How do I supply keys in the following format: {"publicKey":"BDrsEIWlTy1YTAZxpkN1f1C0EcuCjL15j8lxS3KaXzDE_BvlWIHEIGdmsP3hfiiG3ldbF89pWEc6foyFxSOe5es","privateKey":"lDLZKT9oZF07KJYWBZU2zlHfszrK4p9tFtxM-ihpVqs"} (not my actual keys)

Or can I convert this format to PEM file?

andyblarblar commented 1 year ago

The private key can be in either PEM or DER encodings. I have no idea how it's encoded for your example, so I'm not sure what would be best.

See this page in the docs for more info: https://docs.rs/web-push/0.9.2/web_push/struct.VapidSignatureBuilder.html

Hugo-Persson commented 1 year ago

The private key can be in either PEM or DER encodings. I have no idea how it's encoded for your example, so I'm not sure what would be best.

See this page in the docs for more info: https://docs.rs/web-push/0.9.2/web_push/struct.VapidSignatureBuilder.html

If I got my keys from a generator like this

https://www.stephane-quantin.com/en/tools/generators/vapid-keys

What format do I have them in? Sorry if this is stupid question but my knowledge in this is limited.

When I used NodeJS I used this library https://github.com/web-push-libs/web-push

And keys were supplied like this:

webpush.setVapidDetails(
  'mailto:example@yourdomain.org',
  vapidKeys.publicKey,
  vapidKeys.privateKey
);
Hugo-Persson commented 1 year ago

The public key I have is the same public key I use on client side when subscribing to push

andyblarblar commented 1 year ago

The public key is fine as it is. I think all you need to do here is just sandwich the raw base64 encoded bytes in between the PEM headers.

https://tomeko.net/online_tools/base64_to_PEM.php?lang=en

Looks like it may work, if you select the EC Option.

It's a little hard to answer your question because each site uses their own crypto libraries on the backend, and I don't know what format they spit out.

Hugo-Persson commented 1 year ago

The public key is fine as it is. I think all you need to do here is just sandwich the raw base64 encoded bytes in between the PEM headers.

https://tomeko.net/online_tools/base64_to_PEM.php?lang=en

Looks like it may work, if you select the EC Option.

It's a little hard to answer your question because each site uses their own crypto libraries on the backend, and I don't know what format they spit out.

I tried getting converting my key to EC format from that website and putting it in a PEM file and running this

openssl ec -in private.pem -pubout -outform DER|tail -c 65|base64|tr '/+' '_-'|tr -d '\n'

This gives me the following error

read EC key
unable to load Key
8608257536:error:0D07209B:asn1 encoding routines:ASN1_get_object:too long:crypto/asn1/asn1_lib.c:91:
8608257536:error:0D068066:asn1 encoding routines:asn1_check_tlen:bad object header:crypto/asn1/tasn_dec.c:1137:
8608257536:error:0D07803A:asn1 encoding routines:asn1_item_embed_d2i:nested asn1 error:crypto/asn1/tasn_dec.c:309:Type=EC_PRIVATEKEY
8608257536:error:10092010:elliptic curve routines:d2i_ECPrivateKey:EC lib:crypto/ec/ec_asn1.c:1001:
8608257536:error:100DE08E:elliptic curve routines:old_ec_priv_decode:decode error:crypto/ec/ec_ameth.c:464:
8608257536:error:0D07209B:asn1 encoding routines:ASN1_get_object:too long:crypto/asn1/asn1_lib.c:91:
8608257536:error:0D068066:asn1 encoding routines:asn1_check_tlen:bad object header:crypto/asn1/tasn_dec.c:1137:
8608257536:error:0D07803A:asn1 encoding routines:asn1_item_embed_d2i:nested asn1 error:crypto/asn1/tasn_dec.c:309:Type=PKCS8_PRIV_KEY_INFO
8608257536:error:0907B00D:PEM routines:PEM_read_bio_PrivateKey:ASN1 lib:crypto/pem/pem_pkey.c:88:
Hugo-Persson commented 1 year ago

The key I have worked with PHP library, here is what it says about the format

<?php

$auth = [
    'VAPID' => [
        'subject' => 'mailto:me@website.com', // can be a mailto: or your website address
        'publicKey' => '~88 chars', // (recommended) uncompressed public key P-256 encoded in Base64-URL
        'privateKey' => '~44 chars', // (recommended) in fact the secret multiplier of the private key encoded in Base64-URL
        'pemFile' => 'path/to/pem', // if you have a PEM file and can link to it on your filesystem
        'pem' => 'pemFileContent', // if you have a PEM file and want to hardcode its content
    ],
];

How can I convert this type of privateKey to a pem file?

andyblarblar commented 1 year ago

So I looked into it further and found that supporting raw keys was actually pretty easy. I've written a test using a key I generated from the site you linked and its all tested fine, so I've rolled base64 key support out with #36.

In particular, try using VapidSignatureBuilder::from_base64, which is the method that should work for your use case. The site you linked uses URL_SAFE_NO_PAD, btw.

I'm going to close this issue for now, but feel free to reopen it if the new method doesn't work for some reason.

Hugo-Persson commented 1 year ago

So I looked into it further and found that supporting raw keys was actually pretty easy. I've written a test using a key I generated from the site you linked and its all tested fine, so I've rolled base64 key support out with #36.

In particular, try using VapidSignatureBuilder::from_base64, which is the method that should work for your use case. The site you linked uses URL_SAFE_NO_PAD, btw.

I'm going to close this issue for now, but feel free to reopen it if the new method doesn't work for some reason.

Wow thank you so much for your help, going to try right away 👏

Hugo-Persson commented 1 year ago

@andyblarblar The feature worked perfectly for me, thank you 👍