Browse Source

STopping here. Weird behavior while debugging. Sometimes works; sometimes now

home-view-notification-improvements
Matthew Raymer 1 year ago
parent
commit
cf2fec75ea
  1. 27
      package-lock.json
  2. 3
      package.json
  3. 3
      sw_scripts/additional-scripts.js
  4. 19
      sw_scripts/safari-notifications.js
  5. 256
      sw_scripts/secp256k1.js
  6. 3543
      sw_scripts/sw-bn.js
  7. 7
      vue.config.js

27
package-lock.json

@ -12,6 +12,7 @@
"@fortawesome/fontawesome-svg-core": "^6.4.2", "@fortawesome/fontawesome-svg-core": "^6.4.2",
"@fortawesome/free-solid-svg-icons": "^6.4.2", "@fortawesome/free-solid-svg-icons": "^6.4.2",
"@fortawesome/vue-fontawesome": "^3.0.3", "@fortawesome/vue-fontawesome": "^3.0.3",
"@lionello/secp256k1-js": "^1.1.0",
"@pvermeer/dexie-encrypted-addon": "^3.0.0", "@pvermeer/dexie-encrypted-addon": "^3.0.0",
"@tweenjs/tween.js": "^21.0.0", "@tweenjs/tween.js": "^21.0.0",
"@veramo/core": "^5.4.1", "@veramo/core": "^5.4.1",
@ -30,11 +31,13 @@
"dexie": "^3.2.4", "dexie": "^3.2.4",
"dexie-export-import": "^4.0.7", "dexie-export-import": "^4.0.7",
"did-jwt": "^7.2.7", "did-jwt": "^7.2.7",
"elliptic": "^6.5.4",
"ethereum-cryptography": "^2.1.2", "ethereum-cryptography": "^2.1.2",
"ethereumjs-util": "^7.1.5", "ethereumjs-util": "^7.1.5",
"ethr-did-resolver": "^8.1.2", "ethr-did-resolver": "^8.1.2",
"jdenticon": "^3.2.0", "jdenticon": "^3.2.0",
"js-generate-password": "^0.1.9", "js-generate-password": "^0.1.9",
"jssha": "^3.3.1",
"localstorage-slim": "^2.5.0", "localstorage-slim": "^2.5.0",
"luxon": "^3.4.3", "luxon": "^3.4.3",
"merkletreejs": "^0.3.10", "merkletreejs": "^0.3.10",
@ -6058,6 +6061,22 @@
"integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==",
"dev": true "dev": true
}, },
"node_modules/@lionello/secp256k1-js": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@lionello/secp256k1-js/-/secp256k1-js-1.1.0.tgz",
"integrity": "sha512-frvrdwwgWm0gq43rYcGwwZee+k5sX9HfWnB80740h1dvRT0FO0Z6Wt5C5I7bS0dXKy1pt6IomkR1VcXirP+g4Q==",
"dependencies": {
"bn.js": "^4.11.8"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/@lionello/secp256k1-js/node_modules/bn.js": {
"version": "4.12.0",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
},
"node_modules/@noble/ciphers": { "node_modules/@noble/ciphers": {
"version": "0.3.0", "version": "0.3.0",
"resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.3.0.tgz", "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.3.0.tgz",
@ -18859,6 +18878,14 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/jssha": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/jssha/-/jssha-3.3.1.tgz",
"integrity": "sha512-VCMZj12FCFMQYcFLPRm/0lOBbLi8uM2BhXPTqw3U4YAfs4AZfiApOoBLoN8cQE60Z50m1MYMTQVCfgF/KaCVhQ==",
"engines": {
"node": "*"
}
},
"node_modules/keccak": { "node_modules/keccak": {
"version": "3.0.4", "version": "3.0.4",
"resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz", "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz",

3
package.json

@ -12,6 +12,7 @@
"@fortawesome/fontawesome-svg-core": "^6.4.2", "@fortawesome/fontawesome-svg-core": "^6.4.2",
"@fortawesome/free-solid-svg-icons": "^6.4.2", "@fortawesome/free-solid-svg-icons": "^6.4.2",
"@fortawesome/vue-fontawesome": "^3.0.3", "@fortawesome/vue-fontawesome": "^3.0.3",
"@lionello/secp256k1-js": "^1.1.0",
"@pvermeer/dexie-encrypted-addon": "^3.0.0", "@pvermeer/dexie-encrypted-addon": "^3.0.0",
"@tweenjs/tween.js": "^21.0.0", "@tweenjs/tween.js": "^21.0.0",
"@veramo/core": "^5.4.1", "@veramo/core": "^5.4.1",
@ -30,11 +31,13 @@
"dexie": "^3.2.4", "dexie": "^3.2.4",
"dexie-export-import": "^4.0.7", "dexie-export-import": "^4.0.7",
"did-jwt": "^7.2.7", "did-jwt": "^7.2.7",
"elliptic": "^6.5.4",
"ethereum-cryptography": "^2.1.2", "ethereum-cryptography": "^2.1.2",
"ethereumjs-util": "^7.1.5", "ethereumjs-util": "^7.1.5",
"ethr-did-resolver": "^8.1.2", "ethr-did-resolver": "^8.1.2",
"jdenticon": "^3.2.0", "jdenticon": "^3.2.0",
"js-generate-password": "^0.1.9", "js-generate-password": "^0.1.9",
"jssha": "^3.3.1",
"localstorage-slim": "^2.5.0", "localstorage-slim": "^2.5.0",
"luxon": "^3.4.3", "luxon": "^3.4.3",
"merkletreejs": "^0.3.10", "merkletreejs": "^0.3.10",

3
sw_scripts/additional-scripts.js

@ -1,6 +1,3 @@
importScripts("./safari-notifications.js", "./nacl.js");
//importScripts("./nacl.js")
self.addEventListener("push", function (event) { self.addEventListener("push", function (event) {
event.waitUntil((async () => { event.waitUntil((async () => {

19
sw_scripts/safari-notifications.js

@ -1,4 +1,12 @@
async function generateSHA256Hash(data) {
const buffer = new TextEncoder().encode(data);
const hashBuffer = await crypto.subtle.digest('SHA-256', buffer);
const hashArray = Array.from(new Uint8Array(hashBuffer)); // convert buffer to byte array
const hashHex = hashArray.map(byte => byte.toString(16).padStart(2, '0')).join('');
return hashHex;
}
function validateBase64(s) { function validateBase64(s) {
if (!(/^(?:[A-Za-z0-9+\/]{2}[A-Za-z0-9+\/]{2})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?$/.test(s))) { if (!(/^(?:[A-Za-z0-9+\/]{2}[A-Za-z0-9+\/]{2})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?$/.test(s))) {
throw new TypeError('invalid encoding'); throw new TypeError('invalid encoding');
@ -41,7 +49,7 @@ async function getSettingById(id) {
} }
function fetchAllAccounts() { async function fetchAllAccounts() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let openRequest = indexedDB.open('TimeSafariAccounts'); let openRequest = indexedDB.open('TimeSafariAccounts');
@ -80,10 +88,9 @@ async function getNotificationCount() {
const secretUint8Array = self.decodeBase64(secret); const secretUint8Array = self.decodeBase64(secret);
const settings = await getSettingById(1); const settings = await getSettingById(1);
const activeDid = settings['activeDid']; const activeDid = settings['activeDid'];
/**
const accounts = await fetchAllAccounts(); const accounts = await fetchAllAccounts();
/** let did = null;
let result = null; let result = null;
for (var i = 0; i < accounts.length; i++) { for (var i = 0; i < accounts.length; i++) {
let account = accounts[i]; let account = accounts[i];
@ -95,9 +102,9 @@ async function getNotificationCount() {
const messageWithNonceAsUint8Array = decodeBase64(identity); const messageWithNonceAsUint8Array = decodeBase64(identity);
const nonce = messageWithNonceAsUint8Array.slice(0, 24); const nonce = messageWithNonceAsUint8Array.slice(0, 24);
const message = messageWithNonceAsUint8Array.slice(24, identity.length); const message = messageWithNonceAsUint8Array.slice(24, identity.length);
} }
**/
} }
**/
} }
return secret; return secret;
} }

256
sw_scripts/secp256k1.js

@ -0,0 +1,256 @@
(function () {
randomBytes = length => self.crypto.getRandomValues(new Uint8Array(length))
self.Secp256k1 = exports = {}
function uint256(x, base) {
return new BN(x, base)
}
function rnd(P) {
return uint256(randomBytes(32)).umod(P)//TODO red
}
const A = uint256(0)
const B = uint256(7)
const GX = uint256("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16)
const GY = uint256("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16)
const P = uint256("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16)
const N = uint256("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16)
//const RED = BN.red(P)
const _0 = uint256(0)
const _1 = uint256(1)
// function for elliptic curve multiplication in jacobian coordinates using Double-and-add method
function ecmul(_p, _d) {
let R = [_0,_0,_0]
//return (0,0) if d=0 or (x1,y1)=(0,0)
if (_d == 0 || ((_p[0] == 0) && (_p[1] == 0)) ) {
return R
}
let T = [
_p[0], //x-coordinate temp
_p[1], //y-coordinate temp
_p[2], //z-coordinate temp
]
const d = _d.clone()
while (d != 0) {
if (d.testn(0)) { //if last bit is 1 add T to result
R = ecadd(T,R)
}
T = ecdouble(T); //double temporary coordinates
d.iushrn(1); //"cut off" last bit
}
return R
}
function mulmod(a, b, P) {
return a.mul(b).umod(P)//TODO red
}
function addmod(a, b, P) {
return a.add(b).umod(P)//TODO red
}
function invmod(a, P) {
return a.invm(P)//TODO redq
}
function mulG(k) {
const GinJ = AtoJ(GX, GY)
const PUBinJ = ecmul(GinJ, k)
return JtoA(PUBinJ)
}
function assert(cond, msg) {
if (!cond) {
throw Error("assertion failed: " + msg)
}
}
function ecsign(d, z) {
assert(d != 0, "d must not be 0")
assert(z != 0, "z must not be 0")
while (true) {
const k = rnd(P)
const R = mulG(k)
if (R[0] == 0) continue
const s = mulmod(invmod(k, N), addmod(z, mulmod(R[0], d, N), N), N)
if (s == 0) continue
//FIXME: why do I need this
if (s.testn(255)) continue
return {r: toHex(R[0]), s: toHex(s), v: R[1].testn(0) ? 1 : 0}
}
}
function JtoA(p) {
const zInv = invmod(p[2], P)
const zInv2 = mulmod(zInv, zInv, P)
return [mulmod(p[0], zInv2, P), mulmod(p[1], mulmod(zInv, zInv2, P), P)]
}
//point doubling for elliptic curve in jacobian coordinates
//formula from https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates
function ecdouble(_p) {
if (_p[1] == 0) {
//return point at infinity
return [_1, _1, _0]
}
const z2 = mulmod(_p[2], _p[2], P)
const m = addmod(mulmod(A, mulmod(z2, z2, P), P), mulmod(uint256(3), mulmod(_p[0], _p[0], P), P), P)
const y2 = mulmod(_p[1], _p[1], P)
const s = mulmod(uint256(4), mulmod(_p[0], y2, P), P)
const x = addmod(mulmod(m, m, P), negmod(mulmod(s, uint256(2), P), P), P)
return [
x,
addmod(mulmod(m, addmod(s, negmod(x, P), P), P), negmod(mulmod(uint256(8), mulmod(y2, y2, P), P), P), P),
mulmod(uint256(2), mulmod(_p[1], _p[2], P), P)
]
}
function negmod(a, P) {
return P.sub(a)
}
// point addition for elliptic curve in jacobian coordinates
// formula from https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates
function ecadd(_p, _q) {
if (_q[0] == 0 && _q[1] == 0 && _q[2] == 0) {
return _p
}
let z2 = mulmod(_q[2], _q[2], P)
const u1 = mulmod(_p[0], z2, P)
const s1 = mulmod(_p[1], mulmod(z2, _q[2], P), P)
z2 = mulmod(_p[2], _p[2], P)
let u2 = mulmod(_q[0], z2, P)
let s2 = mulmod(_q[1], mulmod(z2, _p[2], P), P)
if (u1.eq(u2)) {
if (!s1.eq(s2)) {
//return point at infinity
return [_1, _1, _0]
}
else {
return ecdouble(_p)
}
}
u2 = addmod(u2, negmod(u1, P), P)
z2 = mulmod(u2, u2, P)
const t2 = mulmod(u1, z2, P)
z2 = mulmod(u2, z2, P)
s2 = addmod(s2, negmod(s1, P), P)
const x = addmod(addmod(mulmod(s2, s2, P), negmod(z2, P), P), negmod(mulmod(uint256(2), t2, P), P), P)
return [
x,
addmod(mulmod(s2, addmod(t2, negmod(x, P), P), P), negmod(mulmod(s1, z2, P), P), P),
mulmod(u2, mulmod(_p[2], _q[2], P), P)
]
}
function AtoJ(x, y) {
return [
uint256(x),
uint256(y),
_1
]
}
function isValidPoint(x, y) {
const yy = addmod(mulmod(mulmod(x, x, P), x, P), B, P)
return yy.eq(mulmod(y, y, P))
}
function toHex(bn) {
return ('00000000000000000000000000000000000000000000000000000000000000000000000000000000' + bn.toString(16)).slice(-64)
}
function decompressKey(x, yBit) {
let redP = BN.red('k256');
x = x.toRed(redP)
const y = x.redMul(x).redMul(x).redAdd(B.toRed(redP)).redSqrt()
const sign = y.testn(0)
return (sign != yBit ? y.redNeg() : y).fromRed()
}
function generatePublicKeyFromPrivateKeyData(pk) {
const p = mulG(pk)
return {x: toHex(p[0]), y: toHex(p[1])}
}
function ecrecover(recId, sigr, sigs, message) {
assert(recId >= 0 && recId <= 3, "recId must be 0..3")
assert(sigr != 0, "sigr must not be 0")
assert(sigs != 0, "sigs must not be 0")
// 1.0 For j from 0 to h (h == recId here and the loop is outside this function)
// 1.1 Let x = r + jn
const x = addmod(uint256(sigr), P.muln(recId >> 1), P)
// 1.2. Convert the integer x to an octet string X of length mlen using the conversion routine
// specified in Section 2.3.7, where mlen = ⌈(log2 p)/8⌉ or mlen = ⌈m/8⌉.
// 1.3. Convert the octet string (16 set binary digits)||X to an elliptic curve point R using the
// conversion routine specified in Section 2.3.4. If this conversion routine outputs “invalid”, then
// do another iteration of Step 1.
//
// More concisely, what these points mean is to use X as a compressed public key.
if (x.gte(P)) {
// Cannot have point co-ordinates larger than this as everything takes place modulo Q.
return null
}
// Compressed keys require you to know an extra bit of data about the y-coord as there are two possibilities.
// So it's encoded in the recId.
const y = decompressKey(x, (recId & 1) == 1)
// 1.4. If nR != point at infinity, then do another iteration of Step 1 (callers responsibility).
// if (!R.mul(N).isInfinity())
// return null
// 1.5. Compute e from M using Steps 2 and 3 of ECDSA signature verification.
const e = uint256(message)
// 1.6. For k from 1 to 2 do the following. (loop is outside this function via iterating recId)
// 1.6.1. Compute a candidate public key as:
// Q = mi(r) * (sR - eG)
//
// Where mi(x) is the modular multiplicative inverse. We transform this into the following:
// Q = (mi(r) * s ** R) + (mi(r) * -e ** G)
// Where -e is the modular additive inverse of e, that is z such that z + e = 0 (mod n). In the above equation
// ** is point multiplication and + is point addition (the EC group operator).
//
// We can find the additive inverse by subtracting e from zero then taking the mod. For example the additive
// inverse of 3 modulo 11 is 8 because 3 + 8 mod 11 = 0, and -3 mod 11 = 8.
const eNeg = negmod(e, N)
const rInv = invmod(sigr, N)
const srInv = mulmod(rInv, sigs, N)
const eNegrInv = mulmod(rInv, eNeg, N)
const R = AtoJ(x, y)
const G = AtoJ(GX, GY)
const qinJ = ecadd(ecmul(G, eNegrInv), ecmul(R, srInv))
const p = JtoA(qinJ)
return {x: toHex(p[0]), y: toHex(p[1])}
}
function ecverify (Qx, Qy, sigr, sigs, z) {
if (sigs == 0 || sigr == 0) {
return false
}
const w = invmod(sigs, N)
const u1 = mulmod(z, w, N)
const u2 = mulmod(sigr, w, N)
const Q = AtoJ(Qx, Qy)
const G = AtoJ(GX, GY)
const RinJ = ecadd(ecmul(G, u1), ecmul(Q, u2))
const r = JtoA(RinJ)
return sigr.eq(r[0])
}
exports.uint256 = uint256
exports.ecsign = ecsign
exports.ecrecover = ecrecover
exports.generatePublicKeyFromPrivateKeyData = generatePublicKeyFromPrivateKeyData
exports.decompressKey = decompressKey
exports.isValidPoint = isValidPoint
exports.ecverify = ecverify
})()

3543
sw_scripts/sw-bn.js

File diff suppressed because it is too large

7
vue.config.js

@ -12,7 +12,12 @@ module.exports = defineConfig({
faviconSVG: "img/icons/safari-pinned-tab.svg", faviconSVG: "img/icons/safari-pinned-tab.svg",
}, },
workboxOptions: { workboxOptions: {
importScripts: ["additional-scripts.js"], importScripts: [
"additional-scripts.js",
"safari-notifications.js",
"nacl.js",
"sw-bn.js",
],
}, },
}, },
}); });

Loading…
Cancel
Save