Genere la clave pública VAPID en Rails y pásela a Javascript

Para utilizar la API Push con VAPID necesito una applicationServerKey :

 serviceWorkerRegistration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: applicationServerKey // we've got it with getApplicationServerKey() defined below }); 

Lo genero en el lado del servidor con Ruby:

 ecdsa_private_key = OpenSSL::PKey::EC.new 'prime256v1' ecdsa_private_key.generate_key sender.vapid_private_key = ecdsa_private_key.to_pem ecdsa_public_key = OpenSSL::PKey::EC.new ecdsa_private_key ecdsa_public_key.private_key = nil sender.vapid_public_key = ecdsa_public_key.to_pem 

Entonces tengo que descargarlo:

 getApplicationServerKey: function () { return new Promise(function (resolve, reject) { var request = new Request('https://example.com/application_server_key'); fetch(request).then(function (response) { response.text().then(function (base64) { resolve(_.base64ToArrayBuffer(base64)); }); }); }); }, base64ToArrayBuffer: function (base64) { var binary_string = window.atob(base64); var len = binary_string.length; var bytes = new Uint8Array(len); for (var i = 0; i < len; i++) { bytes[i] = binary_string.charCodeAt(i); } return bytes.buffer; } 

La clave se devuelve como una cadena base64 desde el controlador:

 ecdsa_public_key = OpenSSL::PKey.read @sender.vapid_public_key base64 = Base64.encode64(ecdsa_public_key.public_key.to_bn.to_s(2)) render text: base64 

El problema es que Firefox devuelve este error cuando llamo pushManager.subscribe :

 DOMException [InvalidAccessError: "Invalid raw ECDSA P-256 public key." code: 15 nsresult: 0x8053000f] 

Cualquier ayuda es apreciada.

ACTUALIZACIÓN : me está volviendo loco … También he intentado codificar / decodificar con hex en lugar de base64, pero obtengo el mismo error.

De Ruby:

 $ ecdsa_public_key.to_text => "Private-Key: (256 bit)\npub: \n 04:28:a9:89:be:8a:a8:f2:f1:bf:ed:04:d2:28:e9:\n 70:e9:b7:f3:8c:3c:f7:20:dc:95:30:1a:72:77:66:\n 09:0d:29:f6:6c:6c:c8:45:6e:da:ac:05:d6:ff:43:\n 9a:66:d0:c3:4c:bc:4a:0f:a3:ad:e8:23:33:22:40:\n 20:9e:de:14:56\n ASN1 OID: prime256v1\n NIST CURVE: P-256\n" $ ecdsa_public_key.public_key.to_bn.to_s 16 => "0428A989BE8AA8F2F1BFED04D228E970E9B7F38C3CF720DC95301A727766090D29F66C6CC8456EDAAC05D6FF439A66D0C34CBC4A0FA3ADE823332240209EDE1456" 

Como puede ver, es una clave P-256 (no sé por qué dice clave privada en lugar de clave pública, pero, como puede ver en el código que la genera, es una clave pública).

Luego descargo la cadena hexadecimal con fetch Javascript y esto es lo que obtengo:

 0428A989BE8AA8F2F1BFED04D228E970E9B7F38C3CF720DC95301A727766090D29F66C6CC8456EDAAC05D6FF439A66D0C34CBC4A0FA3ADE823332240209EDE1456 Array [ "04", "28", "A9", "89", "BE", "8A", "A8", "F2", "F1", "BF", 55 more… ] Uint8Array [ 4, 40, 169, 137, 190, 138, 168, 242, 241, 191, 55 more… ] ArrayBuffer { byteLength: 65 } // I get it by calling .buffer on the Uint8Array DOMException [InvalidAccessError: "Invalid raw ECDSA P-256 public key." code: 15 nsresult: 0x8053000f] 

Como puede ver en los pasos intermedios que imprimo en la consola, la clave se procesa correctamente. Sin embargo sigo teniendo ese error …

ACTUALIZACIÓN 2 : el mismo código funciona correctamente en Chrome: logré enviar una notificación usando VAPID. Probablemente es un error de Firefox.

.buffer eliminando .buffer .

Ahora paso el Uint8Array directamente a la subscribe (en lugar de array.buffer ) y funciona tanto en Chrome como en Firefox.