-
Notifications
You must be signed in to change notification settings - Fork 143
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Nicolas Burtey
committed
Sep 16, 2023
1 parent
ab93735
commit 7f8cec6
Showing
18 changed files
with
694 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -160,3 +160,6 @@ codegen: | |
|
||
gen-test-jwt: | ||
yarn gen-test-jwt | ||
|
||
boltcard: | ||
bun run ./apps/boltcard/index.ts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
*.lockb binary diff=lockb |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
const aesCmac = require("node-aes-cmac").aesCmac | ||
|
||
describe("aes", () => { | ||
test(`testing signature`, async () => { | ||
const c = Buffer.from("E19CCB1FED8892CE", "hex") | ||
const aes_cmac_key = Buffer.from("b45775776cb224c75bcde7ca3704e933", "hex") | ||
|
||
const sv2 = Buffer.from([ | ||
60, 195, 0, 1, 0, 128, 4, 153, 108, 106, 146, 105, 128, 3, 0, 0, | ||
]) | ||
|
||
const options = { returnAsBuffer: true } | ||
const cmac1 = aesCmac(aes_cmac_key, sv2, options) | ||
const cmac2 = aesCmac(cmac1, new Buffer(""), options) | ||
|
||
const halfMac = Buffer.alloc(cmac2.length / 2) | ||
for (let i = 1; i < cmac2.length; i += 2) { | ||
halfMac[i >> 1] = cmac2[i] | ||
} | ||
|
||
console.log({ c, aes_cmac_key, sv2, cmac1, cmac2 }) | ||
expect(Buffer.compare(halfMac, c)).toEqual(0) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import crypto from "crypto" | ||
|
||
// import { AesCmac } from "aes-cmac" | ||
const aesCmac = require("node-aes-cmac").aesCmac | ||
|
||
const aesjs = require("aes-js") | ||
|
||
class DecryptionError extends Error { | ||
constructor(err: Error) { | ||
super(err.message) | ||
} | ||
} | ||
|
||
class UnknownError extends Error {} | ||
|
||
export function aesDecrypt(key: Buffer, data: Buffer): Buffer | DecryptionError { | ||
try { | ||
const aesCtr = new aesjs.ModeOfOperation.cbc(key) | ||
const decryptedBytes = aesCtr.decrypt(data) | ||
return decryptedBytes | ||
} catch (err) { | ||
console.log(err) | ||
if (err instanceof Error) return new DecryptionError(err) | ||
return new UnknownError() | ||
} | ||
} | ||
|
||
export function checkSignature( | ||
uid: Uint8Array, | ||
ctr: Uint8Array, | ||
k2CmacKey: Buffer, | ||
cmac: Buffer, | ||
): boolean { | ||
const sv2 = Buffer.from([ | ||
0x3c, | ||
0xc3, | ||
0x00, | ||
0x01, | ||
0x00, | ||
0x80, | ||
uid[0], | ||
uid[1], | ||
uid[2], | ||
uid[3], | ||
uid[4], | ||
uid[5], | ||
uid[6], | ||
ctr[0], | ||
ctr[1], | ||
ctr[2], | ||
]) | ||
|
||
console.log({ sv2 }) | ||
|
||
let calculatedCmac | ||
|
||
try { | ||
calculatedCmac = getSunMAC(k2CmacKey, sv2) | ||
} catch (error) { | ||
console.error(error) | ||
throw new Error("issue with cMac") | ||
} | ||
|
||
console.log({ calculatedCmac, cmac }) | ||
|
||
// Compare the result | ||
return Buffer.compare(calculatedCmac, cmac) === 0 | ||
} | ||
|
||
function getSunMAC(key: Buffer, sv2: Buffer): Buffer { | ||
// const aesCmac = new AesCmac(key) | ||
// const cmac = Buffer.from(await aesCmac.calculate(sv2)) | ||
|
||
const options = { returnAsBuffer: true } | ||
const fullCmacComputed = aesCmac(key, sv2, options) | ||
|
||
// const cmac = aesCmac(key, sv2, options) | ||
console.log({ fullCmacComputed }) | ||
|
||
const result = Buffer.alloc(fullCmacComputed.length / 2) | ||
for (let i = 1; i < fullCmacComputed.length; i += 2) { | ||
result[i >> 1] = fullCmacComputed[i] | ||
} | ||
|
||
return result | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
|
||
@test "auth: create card" { | ||
RESPONSE=$(curl -s "http://localhost:3000/createboltcard") | ||
CALLBACK_URL=$(echo $RESPONSE | jq -r '.url') | ||
|
||
# Making the follow-up curl request | ||
RESPONSE=$(curl -s "${CALLBACK_URL}") | ||
echo "$RESPONSE" | ||
[[ $(echo $RESPONSE | jq -r '.PROTOCOL_NAME') == "create_bolt_card_response" ]] || exit 1 | ||
} | ||
|
||
|
||
@test "auth: create payment and follow up" { | ||
|
||
P_VALUE="4E2E289D945A66BB13377A728884E867" | ||
C_VALUE="E19CCB1FED8892CE" | ||
|
||
RESPONSE=$(curl -s "http://localhost:3000/ln?p=${P_VALUE}&c=${C_VALUE}") | ||
echo "$RESPONSE" | ||
|
||
CALLBACK_URL=$(echo $RESPONSE | jq -r '.callback') | ||
K1_VALUE=$(echo $RESPONSE | jq -r '.k1') | ||
|
||
echo "CALLBACK_URL: $CALLBACK_URL" | ||
echo "K1_VALUE: $K1_VALUE" | ||
|
||
# Making the follow-up curl request | ||
curl -s "${CALLBACK_URL}?k1=${K1_VALUE}" | ||
} |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import express from "express" | ||
|
||
import { boltcardRouter } from "./router" | ||
import { fetchByK1 } from "./knex" | ||
|
||
boltcardRouter.get("/callback", async (req: express.Request, res: express.Response) => { | ||
const k1 = req?.query?.k1 | ||
const pr = req?.query?.pr | ||
|
||
console.log({ k1, pr }) | ||
|
||
if (!k1 || !pr) { | ||
res.status(400).send({ status: "ERROR", reason: "missing k1 or pr" }) | ||
return | ||
} | ||
|
||
if (typeof k1 !== "string" || typeof pr !== "string") { | ||
res.status(400).send({ status: "ERROR", reason: "invalid k1 or pr" }) | ||
return | ||
} | ||
|
||
const payment = await fetchByK1(k1) | ||
console.log(payment) | ||
// fetch user from k1 | ||
// payInvoice(pr) | ||
|
||
res.json({ status: "OK" }) | ||
}) | ||
|
||
const callback = "dummy" | ||
export { callback } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export const serverUrl = process.env.SERVER_URL ?? "http://localhost:3000" | ||
|
||
const AES_DECRYPT_KEY = process.env.AES_DECRYPT_KEY ?? "0c3b25d92b38ae443229dd59ad34b85d" | ||
|
||
export const aesDecryptKey = Buffer.from(AES_DECRYPT_KEY, "hex") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import { aesDecrypt, checkSignature } from "./aes" | ||
import { decryptedPToUidCtr } from "./decoder" | ||
|
||
const aesjs = require("aes-js") | ||
|
||
const values = [ | ||
{ | ||
p: aesjs.utils.hex.toBytes("4E2E289D945A66BB13377A728884E867"), | ||
c: Buffer.from("E19CCB1FED8892CE", "hex"), | ||
aes_decrypt_key: aesjs.utils.hex.toBytes("0c3b25d92b38ae443229dd59ad34b85d"), | ||
aes_cmac_key: Buffer.from("b45775776cb224c75bcde7ca3704e933", "hex"), | ||
decrypted_uid: "04996c6a926980", | ||
decrypted_ctr: "030000", | ||
decoded_ctr: 3, | ||
}, | ||
// { | ||
// p: aesjs.utils.hex.toBytes("00F48C4F8E386DED06BCDC78FA92E2FE"), | ||
// c: Buffer.from("66B4826EA4C155B4", "hex"), | ||
// aes_decrypt_key: aesjs.utils.hex.toBytes("0c3b25d92b38ae443229dd59ad34b85d"), | ||
// aes_cmac_key: Buffer.from("b45775776cb224c75bcde7ca3704e933", "hex"), | ||
// decrypted_uid: "04996c6a926980", | ||
// decrypted_ctr: "050000", | ||
// decoded_ctr: 5, | ||
// }, | ||
// { | ||
// p: aesjs.utils.hex.toBytes("0DBF3C59B59B0638D60B5842A997D4D1"), | ||
// c: aesjs.utils.hex.toBytes("66B4826EA4C155B4"), | ||
// aes_decrypt_key: aesjs.utils.hex.toBytes("0c3b25d92b38ae443229dd59ad34b85d"), | ||
// aes_cmac_key: aesjs.utils.hex.toBytes("b45775776cb224c75bcde7ca3704e933"), | ||
// decrypted_uid: "04996c6a926980", | ||
// decrypted_ctr: "070000", | ||
// decoded_ctr: 7, | ||
// }, | ||
] | ||
|
||
describe("crypto", () => { | ||
values.forEach( | ||
({ | ||
p, | ||
c, | ||
aes_decrypt_key, | ||
aes_cmac_key, | ||
decrypted_uid, | ||
decrypted_ctr, | ||
decoded_ctr, | ||
}) => { | ||
test(`testing ${aesjs.utils.hex.fromBytes(p)}`, async () => { | ||
const decryptedP = aesDecrypt(aes_decrypt_key, p) | ||
if (decryptedP instanceof Error) { | ||
throw decryptedP | ||
} | ||
|
||
const { uid, uidRaw, ctr, ctrRawInverseBytes } = decryptedPToUidCtr(decryptedP) | ||
|
||
expect(uid).toEqual(decrypted_uid) | ||
expect(ctr).toEqual(decoded_ctr) | ||
// expect(ctrRawInverseBytes).toEqual(decrypted_ctr) | ||
|
||
console.log({ uidRaw, ctrRawInverseBytes, aes_cmac_key, c }) | ||
|
||
const cmacVerified = checkSignature(uidRaw, ctrRawInverseBytes, aes_cmac_key, c) | ||
expect(cmacVerified).toEqual(true) | ||
}) | ||
}, | ||
) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
const aesjs = require("aes-js") | ||
|
||
export const decryptedPToUidCtr = ( | ||
decryptedP: Uint8Array, | ||
): { uid: string; uidRaw: Uint8Array; ctr: number; ctrRawInverseBytes: Uint8Array } => { | ||
if (decryptedP[0] !== 0xc7) { | ||
throw new Error("data not starting with 0xC7") | ||
} | ||
|
||
const uidRaw = decryptedP.slice(1, 8) | ||
const uid = aesjs.utils.hex.fromBytes(uidRaw) | ||
|
||
const ctrRawInverseBytes = decryptedP.slice(8, 11) | ||
const ctr = | ||
(ctrRawInverseBytes[2] << 16) | (ctrRawInverseBytes[1] << 8) | ctrRawInverseBytes[0] | ||
|
||
return { | ||
uid, | ||
uidRaw, | ||
ctr, | ||
ctrRawInverseBytes, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
version: "3" | ||
services: | ||
boltcard-pg: | ||
image: postgres:14.1 | ||
ports: | ||
- "5436:5432" | ||
expose: | ||
- "5432" | ||
environment: | ||
- POSTGRES_USER=dbuser | ||
- POSTGRES_PASSWORD=secret | ||
- POSTGRES_DB=default |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// server.js | ||
|
||
import express from "express" | ||
import bodyParser from "body-parser" | ||
|
||
import { boltcardRouter } from "./router" | ||
|
||
// loading router | ||
import { lnurlw } from "./lnurlw" | ||
import { callback } from "./callback" | ||
import { createboltcard } from "./new" | ||
import { createTable } from "./knex" | ||
|
||
lnurlw | ||
callback | ||
createboltcard | ||
|
||
await createTable() | ||
|
||
const app = express() | ||
const PORT = 3000 | ||
|
||
// Middleware to parse POST requests | ||
app.use(bodyParser.json()) | ||
app.use(bodyParser.urlencoded({ extended: true })) | ||
|
||
// Use the router | ||
app.use(boltcardRouter) | ||
|
||
// Start the server | ||
app.listen(PORT, () => { | ||
console.log(`Server started on http://localhost:${PORT}`) | ||
}) |
Oops, something went wrong.