Giter VIP home page Giter VIP logo

webcrypto-web-push's People

Contributors

maxholman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

webcrypto-web-push's Issues

cf-jwt folder missing from bundle

Hello,

In trying to deploy my app to cloudflare I am receiving this error:

23:41:53.259 | [vite-plugin-pwa:build] Could not resolve "./cf-jwt/main.js" from "node_modules/@block65/webcrypto-web-push/dist/lib/vapid.js"
-- | --
23:41:53.259 | file: /opt/buildhome/repo/node_modules/@block65/webcrypto-web-push/dist/lib/vapid.js
23:41:53.262 | error during build:
23:41:53.263 | RollupError: Could not resolve "./cf-jwt/main.js" from "node_modules/@block65/webcrypto-web-push/dist/lib/vapid.js"
23:41:53.263 | at error (file:///opt/buildhome/repo/node_modules/rollup/dist/es/shared/node-entry.js:2245:30)

It seems that the npm package does not include the file at dist/lib/cf-jwt
https://www.npmjs.com/package/@block65/webcrypto-web-push?activeTab=code

But I do see the cf-jwt folder in github https://github.com/block65/webcrypto-web-push/tree/master/lib/cf-jwt

Should it be included in the released bundle?

Thanks

Issue with imports

It seems like its impossible to import the package

import {
	type PushSubscription,
	type PushMessage,
	type VapidKeys,
	buildPushPayload
} from '@block65/webcrypto-web-push';

image

Does not work with `wns2-pn1p.notify.windows.com` (Windows Notification Service)

sending something to wns2-pn1p.notify.windows.com results in the following error (response headers):

{
    "x-wns-error-description": "Zero or duplicate tokens or token signing keys.",
    "x-wns-notificationstatus": "dropped",
    "x-wns-status": "dropped"
}

See alastaircoote/webpush-webcrypto#5 which can be made to behave the same as your library with:

request.headers['Encryption'] = `keyid=p256dh;${request.headers['Encryption']}`;
request.headers['Crypto-Key'] = `keyid=p256dh;${filter(request.headers['Crypto-Key'])}`;
function filter(str, include, ...keys) {
  const          pairs = str.split(';').map(pair => pair.trim());
  const  filteredPairs = pairs.filter(pair => { const key = pair.split('=')[0]; return include ? keys.includes(key) : !keys.includes(key); });
  return filteredPairs.join(';');
}

scratch.js

<script>
  const id = {
    "P": "",
    "p": "" // pkcs8
  };
  const ID = { publicKey: id.P, privateKey: id.p };
  const message = { data: "You've got mail!" };
  const subscription = {
      "endpoint": "https://wns2-pn1p.notify.windows.com/w/?token=BQYAAABvp59EVrscIXz82bXgaceSDSDjODHmHkbaesMsajXKnsHMRblD9KCsBcCBqyD9t0%2bMpzykYZDifrSx%2fjlcrvSiGOej2SuB%2bvJMt7X6QRyReMRu5fE22qhaVNEbAPeXDHJei07tV%2fUDW97ej0VNNZGyvUrw1tqgYQw6r7Xc372NnvLehPwoqkSpq8tLN7Uy9WCCXusRm9yoC4XJ3jWy812UexJZVSD94FhtEcdOfZ61u5HPahq9GgY89Nlio21ZRgWwr21ZDzGrlmXu9a8vujWcI8IqqIjdZVvWHnK3gHyxRiuHMrSKDETszRJTEvzKADA%3d",
      "expirationTime": null,
      "keys": {
          "p256dh": "BPy_jJEqmdSYVnSyw_sr-CVFR7sTtdQePNJyQITlsBm1pz2cmdG6HQ1terT3ngoNpbC0ia-uKoU0sK8s5CUehy0",
          "auth": "_GeuNaTkwdxxNlXn-FE6bg"
      }
  };
  const adminContact = 'mailto:[email protected]';
</script>

<script type=module>
// https://cdn.jsdelivr.net/npm/webpush-webcrypto/+esm
  function e(e){let t=e;"string"==typeof t&&(t=(new TextEncoder).encode(t));let n="";return new Uint8Array(t).forEach((e=>{n+=String.fromCharCode(e)})),btoa(n).replace(/=/g,"").replace(/\+/g,"-").replace(/\//g,"_")}function t(e){let t=e.replace(/\-/g,"+").replace(/_/g,"/");const n=4-t.length%4;if(4!==n)for(let e=0;e<n;e++)t+="=";if(t.length%4!=0)throw new Error("Decoded to incorrect length");const r=atob(t),a=new Uint8Array(r.length);for(let e=0;e<r.length;e++)a[e]=r.charCodeAt(e);return a.buffer}function n(e){const t=e.reduce(((e,t)=>e+t.byteLength),0);let n=0;const r=new Uint8Array(t);for(const t of e)r.set(t,n),n+=t.byteLength;return r}let r;"undefined"!=typeof self&&(r=self.crypto);const a={get subtle(){if(!r)throw new Error("Could not find global Crypto module. Please set it with the setCrypto method.");return r.subtle},getRandomValues(e){if(!r)throw new Error("Could not find global Crypto module. Please set it with the setCrypto method.");return r.getRandomValues(e)}};function o(e){r=e}const i=new TextEncoder,c=i.encode("Content-Encoding: auth\0"),s=i.encode("P-256\0"),u=i.encode("Content-Encoding: nonce\0"),l=i.encode("Content-Encoding: aesgcm\0"),y={typ:"JWT",alg:"ES256"};async function p({options:t,payloadLength:n,salt:r,localPublicKey:o}){const i=await a.subtle.exportKey("raw",o),c=await a.subtle.exportKey("raw",t.applicationServerKeys.publicKey),s=e(i),u=e(c),l=new URL(t.target.endpoint),p=await async function(t,n){if(!t.privateKey||!t.publicKey)throw new Error("Missing public or private key");const r=Math.floor(Date.now()/1e3)+43200,o={aud:n.aud,exp:r,sub:n.sub},i=e(JSON.stringify(y)),c=e(JSON.stringify(o)),s=i+"."+c;return i+"."+c+"."+e(await a.subtle.sign({name:"ECDSA",hash:{name:"SHA-256"}},t.privateKey,(new TextEncoder).encode(s)))}(t.applicationServerKeys,{aud:l.origin,sub:t.adminContact}),w={Encryption:`salt=${e(r)}`,"Crypto-Key":`dh=${s}; p256ecdsa=${u}`,"Content-Length":n.toString(),"Content-Type":"application/octet-stream","Content-Encoding":"aesgcm",Authorization:`WebPush ${p}`,TTL:t.ttl.toString()};return t.topic&&(w.Topic=t.topic),t.urgency&&(w.Urgency=t.urgency),w}async function w(e){const r=await a.subtle.generateKey({name:"ECDH",namedCurve:"P-256"},!0,["deriveBits"]);if(!r.privateKey||!r.publicKey)throw new Error("Local key generation failed");const o=await async function(e){const n=t(e.auth);if(16!==n.byteLength)throw new Error(`incorrect auth length, expected 16 bytes got ${n.byteLength}`);return{auth:n,p256:await a.subtle.importKey("raw",t(e.p256dh),{name:"ECDH",namedCurve:"P-256"},!0,[])}}(e.target.keys),i=await async function(e,t){const n=await a.subtle.deriveBits({name:"ECDH",public:e},t,256);return a.subtle.importKey("raw",n,{name:"HKDF"},!1,["deriveBits","deriveKey"])}(o.p256,r.privateKey),y=await async function(e,t){const n=await a.subtle.deriveBits({name:"HKDF",hash:"SHA-256",salt:e,info:c},t,256);return a.subtle.importKey("raw",n,"HKDF",!1,["deriveBits"])}(o.auth,i),w=await async function(e,t){const r=await a.subtle.exportKey("raw",e),o=await a.subtle.exportKey("raw",t);return n([s,new Uint8Array([0,r.byteLength]),new Uint8Array(r),new Uint8Array([0,o.byteLength]),new Uint8Array(o)])}(o.p256,r.publicKey),d=new Uint8Array(16);a.getRandomValues(d);const g=await async function(e,t,r){const o=n([u,r]);return a.subtle.deriveBits({name:"HKDF",hash:"SHA-256",salt:t,info:o},e,96)}(y,d,w),h=await async function(e,t,r){const o=n([l,r]),i=await a.subtle.deriveBits({name:"HKDF",hash:"SHA-256",salt:t,info:o},e,128);return a.subtle.importKey("raw",i,"AES-GCM",!1,["encrypt"])}(y,d,w),b=function(e){let t=Math.round(100*Math.random());const r=e.byteLength+2+t;r>4078&&(t-=r-4078);const a=new Uint8Array(2+t);return new DataView(a.buffer).setUint16(0,t),n([a,e])}((new TextEncoder).encode(e.payload)),f=await a.subtle.encrypt({name:"AES-GCM",iv:g},h,b);return{headers:await p({options:e,payloadLength:f.byteLength,salt:d,localPublicKey:r.publicKey}),body:f,endpoint:e.target.endpoint}}class d{constructor(e,t){this.publicKey=e,this.privateKey=t}async toJSON(){const t=await a.subtle.exportKey("raw",this.publicKey),n=await a.subtle.exportKey("pkcs8",this.privateKey);return{publicKey:e(t),privateKey:e(n)}}static async fromJSON(e){const n=await a.subtle.importKey("raw",t(e.publicKey),{name:"ECDSA",namedCurve:"P-256"},!0,[]),r=await a.subtle.importKey("pkcs8",t(e.privateKey),{name:"ECDSA",namedCurve:"P-256"},!0,["sign"]);return new d(n,r)}static async generate(){const e=await a.subtle.generateKey({name:"ECDSA",namedCurve:"P-256"},!0,["sign"]);if(console.log("got private?"),!e.publicKey||!e.privateKey)throw new Error("Did not generate both public and private key somehow");return new d(e.publicKey,e.privateKey)}}
  const [ ApplicationServerKeys, generatePushHTTPRequest ] = [ d, w ];

  function filter(str, include, ...keys) {
    const          pairs = str.split(';').map(pair => pair.trim());
    const  filteredPairs = pairs.filter(pair => { const key = pair.split('=')[0]; return include ? keys.includes(key) : !keys.includes(key); });
    return filteredPairs.join(';');
  }

  const applicationServerKeys = await ApplicationServerKeys.fromJSON(ID);
  const request = await generatePushHTTPRequest({ applicationServerKeys, target: subscription, payload: { data: 'test' }, ttl: 60 });
  if (1) {
    request.headers['Encryption'] = `keyid=p256dh;${request.headers['Encryption']}`;
    request.headers['Crypto-Key'] = `keyid=p256dh;${filter(request.headers['Crypto-Key'])}`;
  }

  delete request.endpoint;
  request.method = 'POST';

  const f = `await fetch('${subscription.endpoint}', ${JSON.stringify(request)})`; console.warn(f); // @maxholman – don't worry about the body; server complains about the headers!
</script>

<script type=module>
  import { buildPushPayload } from '//js.efn.kr/npm/@block65/webcrypto-web-push/+esm';
  const vapid = { subject: adminContact, publicKey: id.P, privateKey: 'cCLvfK0eWp1uJFRc0Srmx2Ne1NYPSX6_YGnJnRtATGu' };
  const request = await buildPushPayload(message, subscription, vapid);
  
  const f = `await fetch('${subscription.endpoint}', ${JSON.stringify(request)})`; console.warn(f); // @maxholman – don't worry about the body; server complains about the headers!
</script>

Cloudflare Workers encountered an error.

X [ERROR] Could not resolve "node:crypto"

node_modules/@block65/webcrypto-web-push/dist/lib/isomorphic-crypto.js:3:13:
  3 │     : import('node:crypto'));
    ╵              ~~~~~~~~~~~~~

The package "node:crypto" wasn't found on the file system but is built into node. Are you trying
to bundle for node? You can use "platform: 'node'" to do that, which will remove this error.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.