You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

2.6 KiB

NOTES on working with Cryptographic Keys

Since the VAPID key pair was created using cyprto.createECDH we could reconstitute our public key using only the private key:

    const curveName = 'prime256v1';
    const ecdh = crypto.createECDH(curveName);
    const privateKeyBuffer = Buffer.from(privateKey, 'base64');
    ecdh.setPrivateKey(privateKeyBuffer);
    const rawPublicKeyBuffer = ecdh.getPublicKey();
    

Unfortunately, crypto module creates only "raw" keys. And when working with jsonwebtoken.sign method we must have a PEM or something with ASN metadata. So, we create PEMs using eckeys-util module:

    const pems = ecKeyUtils.generatePem({curveName, privateKey: ecdh.getPrivateKey(), publicKey: rawPublicKeyBuffer });

    console.log("privateKey: ", pems.privateKey);
    console.log();
    console.log("publicKey: ", pems.publicKey);

    const jwtToken = jwt.sign(jwtInfo, pems.privateKey, { algorithm: 'ES256' });

I trie here to create my own ASN1 metadata but this seems doomed due to ignorance of what were the required components:

    const asn1Header = Buffer.from('3059301306072a8648ce3d020106082a8648ce3d030107034200', 'hex');
    const derPublicKeyBuffer = Buffer.concat([asn1Header, rawPublicKeyBuffer]);
    const base64DerPublicKey = derPublicKeyBuffer.toString('base64');
    console.log("base64DerPublicKey: ", base64DerPublicKey)

Such an approach creates a DER key pair. An alternative to that method is:

    const ders = ecKeyUtils.generateDer({curveName, privateKey: ecdh.getPrivateKey(), publicKey: rawPublicKeyBuffer });
    console.log("privateKey: ", ders.privateKey);
    console.log("publicKey: ", ders.publicKey);

... using eckeys-util again ... but I'm not 100% sure if these have all the necessary ASN1 metadata AND the DER key will produce this error ...

Error: secretOrPrivateKey must be an asymmetric key when using ES256
    at module.exports [as sign] (/usr/src/app/node_modules/jsonwebtoken/sign.js:124:22)

... when used in the sign method. So, apparently, sign does not like the DER binary format but it is fine with PEM.

When sending a notification request to the Mozilla endpoint it does not like the Crypto-Key header:

{
  "code":400,
  "errno":110,
  "error":"Bad Request",
  "message":"Invalid aes128gcm Crypto-Key header",
  "more_info":"http://autopush.readthedocs.io/en/latest/http.html#error-codes"
}

fcm.google.com push server:

authorization header had invalid format. authorization header should have the following format: t=jwtToken; k=base64(publicApplicationServerKey)

403