当前位置: 首页 > 知识库问答 >
问题:

用Java实现Web Push API的消息加密

房冥夜
2023-03-14

我试图创建一个能够使用推送API发送推送消息的服务器:https://developer.mozilla.org/en-us/docs/web/api/push_api

在sheltond的帮助下,我能够找出一些应该工作但不工作的代码。

当我将加密消息发送到推送服务时,我会得到预期的201状态码,但推送从未到达Firefox。如果我删除有效负载和头,并简单地向相同的URL发送一个POST请求,消息就会成功地到达Firefox中,没有任何数据。我怀疑这可能与我使用cipher.getInstance(“AES/GCM/Nopadding”)加密数据的方式有关;

这是我目前使用的代码:

try {
    final byte[] alicePubKeyEnc = Util.fromBase64("BASE_64_PUBLIC_KEY_FROM_PUSH_SUBSCRIPTION");
    KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");
    ECGenParameterSpec kpgparams = new ECGenParameterSpec("secp256r1");
    kpg.initialize(kpgparams);

    ECParameterSpec params = ((ECPublicKey) kpg.generateKeyPair().getPublic()).getParams();
    final ECPublicKey alicePubKey = fromUncompressedPoint(alicePubKeyEnc, params);
    KeyPairGenerator bobKpairGen = KeyPairGenerator.getInstance("EC");
    bobKpairGen.initialize(params);

    KeyPair bobKpair = bobKpairGen.generateKeyPair();
    KeyAgreement bobKeyAgree = KeyAgreement.getInstance("ECDH");
    bobKeyAgree.init(bobKpair.getPrivate());


    byte[] bobPubKeyEnc = toUncompressedPoint((ECPublicKey) bobKpair.getPublic());


    bobKeyAgree.doPhase(alicePubKey, true);
    Cipher bobCipher = Cipher.getInstance("AES/GCM/NoPadding");
    SecretKey bobDesKey = bobKeyAgree.generateSecret("AES");
    byte[] saltBytes = new byte[16];
    new SecureRandom().nextBytes(saltBytes);
    Mac extract = Mac.getInstance("HmacSHA256");
    extract.init(new SecretKeySpec(saltBytes, "HmacSHA256"));
    final byte[] prk = extract.doFinal(bobDesKey.getEncoded());

    // Expand
    Mac expand = Mac.getInstance("HmacSHA256");
    expand.init(new SecretKeySpec(prk, "HmacSHA256"));
    String info = "Content-Encoding: aesgcm128";
    expand.update(info.getBytes(StandardCharsets.US_ASCII));
    expand.update((byte) 1);
    final byte[] key_bytes = expand.doFinal();

    // Use the result
    SecretKeySpec key = new SecretKeySpec(key_bytes, 0, 16, "AES");
    bobCipher.init(Cipher.ENCRYPT_MODE, key);

    byte[] cleartext = "{\"this\":\"is a test that is supposed to be working but it is not\"}".getBytes();
    byte[] ciphertext = bobCipher.doFinal(cleartext);

    URL url = new URL("PUSH_ENDPOINT_URL");
    HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
    urlConnection.setRequestMethod("POST");
    urlConnection.setRequestProperty("Content-Length", ciphertext.length + "");
    urlConnection.setRequestProperty("Content-Type", "application/octet-stream");
    urlConnection.setRequestProperty("Encryption-Key", "keyid=p256dh;dh=" + Util.toBase64UrlSafe(bobPubKeyEnc));
    urlConnection.setRequestProperty("Encryption", "keyid=p256dh;salt=" + Util.toBase64UrlSafe(saltBytes));
    urlConnection.setRequestProperty("Content-Encoding", "aesgcm128");
    urlConnection.setDoInput(true);
    urlConnection.setDoOutput(true);
    final OutputStream outputStream = urlConnection.getOutputStream();
    outputStream.write(ciphertext);
    outputStream.flush();
    outputStream.close();
    if (urlConnection.getResponseCode() == 201) {
        String result = Util.readStream(urlConnection.getInputStream());
        Log.v("PUSH", "OK: " + result);
    } else {
        InputStream errorStream = urlConnection.getErrorStream();
        String error = Util.readStream(errorStream);
        Log.v("PUSH", "Not OK: " + error);
    }
} catch (Exception e) {
    Log.v("PUSH", "Not OK: " + e.toString());
}

提前感谢您的帮助

共有1个答案

吴英武
2023-03-14

根据https://jrconlin.github.io/webpushdatatestpage/更改代码后能够接收通知

在下面找到修改后的代码:

 

 类似资料:
  • 本文向大家介绍Java加密 消息摘要算法SHA实现详解,包括了Java加密 消息摘要算法SHA实现详解的使用技巧和注意事项,需要的朋友参考一下 SHA是消息摘要算法的一种实现方式,前面已经总结过MD2\4\5的实现,接下来就为大家总结一下SHA的实现。 SHA的jdk实现: SHA的BC实现: 对于SHA224,JAVA jdk并没有提供实现,下面是利用BC实现的方法: 对于SHA224还有一种类

  • 本文向大家介绍Java加密 消息摘要算法MAC实现详解,包括了Java加密 消息摘要算法MAC实现详解的使用技巧和注意事项,需要的朋友参考一下 MAC是消息摘要算法的第三种实现方式,另外两种方式分别为:MD2\4\5、SHA。 MAC的jdk实现:1、默认密钥方式 2、动态密钥方式: MAC的BC实现: 到今天JAVA中的Base64、对称加密、消息摘要加密的实现总结就完工了,如果哪位对此感兴趣,

  • 一、前言 上一章《Memcached源码分析 - Memcached源码分析之命令解析(2)》,我们花了很大的力气去讲解Memcached如何从客户端读取命令,并且解析命令,然后处理命令并且向客户端回应消息。 这一章,我们主要来讲解Memcached回应消息的技术细节。 本章前,我们先需要了解几个知识点(msghdr和iovc)。 msghdr结构: struct msghdr { v

  • 问题内容: 我有一个大的字节数组和rsa密钥对,由值1024初始化。强烈要求使用rsa加密和指定的密钥大小,因此无法更改它。因此,我不能将对称加密与不对称加密对称密钥一起使用。我不能使用其他任何键。我有一个字节数组,需要返回加密的字节数组。我想知道是否有现成的工具可以解决这个问题? 很抱歉出现这样的业余问题,但我确实需要帮助。 问题答案: 如前所述,您的问题只有一个答案,那就是“否”。RSA加密是

  • 问题内容: 我有一个包含在byte []中的消息,该消息已用“ RSA / ECB / PKCS1Padding”加密。为了解密它,我创建了一个Cipher c并用 直到现在,我只使用 doFinal() 方法解密了小消息,并返回一个包含已解密字节的byte []。 但是在这种情况下,数据会更大(大约500字节),并且 doFinal() 方法会引发异常(javax.crypto.IllegalB