在Rails中生成VAPID公钥并将其传递给Javascript [英] Generate the VAPID public key in Rails and pass it to Javascript

查看:226
本文介绍了在Rails中生成VAPID公钥并将其传递给Javascript的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了在VAPID中使用Push API,我需要一个 applicationServerKey

  serviceWorkerRegistration.pushManager.subscribe({
userVisibleOnly:true,
applicationServerKey:applicationServerKey //我们已经在get
}下面定义了getApplicationServerKey()

我在服务器端用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


$ b然后,我必须下载它:
$ b $ pre $ getApplicationServerKey: {
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); (var i = 0; i bytes [i] = binary_string.charCodeAt(i);

}
返回bytes.buffer;

$ c


$ b

键从控制器返回一个base64字符串:

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

问题是,当我调用 pushManager.subscribe

  DOMException [InvalidAccessError: P-256公钥。 
code:15
nsresult:0x8053000f]

任何帮助表示赞赏。 / p>

更新:这让我发疯了...我也尝试使用十六进制编码/解码而不是base64,但是我得到相同的错误。



从Ruby:

  $ ecdsa_public_key.to_text 
=> Private Key:(256位)\ npub:\ n
04:28:a9:89:be:8a:a8:f2:f1:bf:ed:04:d2:28:e9: \ $
70:e9:b7:f3:8c:3c:f7:20:dc:95:30:1a:72:77:66:\\\

09:0d:29: f6:6c:6c:c8:45:6e:da:ac:05:d6:ff:43:\\\

9a:66:d0:c3:4c:bc:4a:0f:a3:ad :e8:23:33:22:40:\ n
20:9e:de:14:56 \ $
ASN1 OID:prime256v1\
NIST曲线:P- 256 \\\


$ ecdsa_public_key.public_key.to_bn.to_s 16
=> 0428A989BE8AA8F2F1BFED04D228E970E9B7F38C3CF720DC95301A727766090D29F66C6CC8456EDAAC05D6FF439A66D0C34CBC4A0FA3ADE823332240209EDE1456

正如你所看到的,它是一个P-256键(我不知道为什么它说Private-Key而不是Public Key,但是,正如你从代码中看到的那样,它是一个公钥)。

然后我下载hex字符串与JavaScript fetch 这是我得到:

  0428A989BE8AA8F2F1BFED04D228E970E9B7F38C3CF720DC95301A727766090D29F66C6CC8456EDAAC05D6FF439A66D0C34CBC4A0FA3ADE823332240209EDE1456 
$ b $ Array [04,28,A9,89,BE,8A,A8,F2,F1,BF,55更多...]

Uint8Array [4,40,169,137,190,138,168,242,241,191,55更多...]

ArrayBuffer {byteLength:65 } //我通过调用Uint8Array上的.buffer来得到它

DOMException [InvalidAccessError:原始ECDSA P-256公钥。
code:15
nsresult:0x8053000f]

正如您从我在控制台中打印的中间步骤,键被正确处理。然而,我仍然得到这个错误...



更新2 :相同的代码在Chrome中成功运行:我设法发送通知使用VAPID 。这可能是一个Firefox的bug。

解决方案

我通过删除 .buffer

现在我将 Uint8Array 直接传递给 subscribe (而不是 array.buffer ),它可以在Chrome和Firefox上使用。


In order to use the Push API with VAPID I need an applicationServerKey:

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

I generate it on the server side with 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

Then I have to download it:

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;
}

The key is returned as a base64 string from the controller:

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

The problem is that Firefox returns this error when I call pushManager.subscribe:

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

Any help is appreciated.

UPDATE: it's driving me crazy... I've also tried encoding / decoding with hex instead of base64, but I get the same error.

From 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"

As you can see it is a P-256 key (I don't know why it says Private-Key instead of Public Key, but, as you can see from the code that generates it, it is a public key).

Then I download the hex string with Javascript fetch and this is what I get:

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]

As you can see from the intermediate steps that I print in the console, the key is processed correctly. However I still get that error...

UPDATE 2: The same code works successfully in Chrome: I managed to send a notification using VAPID. It's probably a Firefox bug.

解决方案

I solved by removing .buffer.

Now I pass the Uint8Array directly to subscribe (instead of array.buffer) and it works both on Chrome and Firefox.

这篇关于在Rails中生成VAPID公钥并将其传递给Javascript的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆