Skip to content

Commit

Permalink
clean up and update test
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewkmin committed Aug 19, 2024
1 parent 3a20f2a commit d531b43
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 83 deletions.
8 changes: 4 additions & 4 deletions examples/browser-api-key-stamper/README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
# Example: `browser-api-key-stamper`

This example takes a Turnkey API key and uses it to authenticate (stamp) a `whoami` request. This is primarily a utility example to test encoding functionality, as opposed to being a real customer-facing example.
This example takes a Turnkey API key and uses it to authenticate (stamp) a `whoami` request. This is primarily a utility example to test encoding functionality within a browser context (i.e. using webcrypto libraries), as opposed to being a real customer-facing example. Given the sensitivity of API keys, we recommend only using them in the browser context for testing purposes, or if you really know what you're doing.

## Getting started

### 1/ Cloning the example

Make sure you have `node` installed locally; we recommend using Node v16+.
Make sure you have `node` installed locally; we recommend using Node v18+.

```bash
$ git clone https://github.com/tkhq/sdk
$ cd sdk/
$ corepack enable # Install `pnpm`
$ pnpm install -r # Install dependencies
$ pnpm run build-all # Compile source code
$ cd examples/email-auth/
$ cd examples/browser-api-key-stamper/
```

### 2/ Setting up Turnkey
Expand Down Expand Up @@ -43,4 +43,4 @@ Now open `.env.local` and add the missing environment variables:
$ pnpm run dev
```

This command will run a NextJS app on port 3000. If you navigate to http://localhost:3000 in your browser, you can follow the prompts to start an email auth.
This command will run a NextJS app on port 3000. If you navigate to http://localhost:3000 in your browser, you can follow the prompts to enter an API keypair. Then, clicking the `Whoami` button should yield a successful response from Turnkey containing your organization + user details.
2 changes: 1 addition & 1 deletion examples/browser-api-key-stamper/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "@turnkey/example-email-auth",
"name": "@turnkey/example-browser-api-key-stamper",
"version": "0.1.0",
"private": true,
"scripts": {
Expand Down
5 changes: 1 addition & 4 deletions examples/browser-api-key-stamper/src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,7 @@ export default function WhoamiPage() {
/>
</a>

<form
className={styles.form}
onSubmit={whoamiFormSubmit(whoami)}
>
<form className={styles.form} onSubmit={whoamiFormSubmit(whoami)}>
<label className={styles.label}>
API Private Key
<input
Expand Down
86 changes: 19 additions & 67 deletions packages/api-key-stamper/src/__tests__/utils-test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import { test, expect } from "@jest/globals";
import { convertTurnkeyApiKeyToJwk } from "../utils";
import { readFixture } from "../__fixtures__/shared";
import { assertValidSignature } from "./shared";
import { generateP256KeyPair } from "@turnkey/crypto";
import * as crypto from "crypto";
import { uint8ArrayFromHexString } from "@turnkey/encoding";
import { signWithApiKey as signWeb } from "../webcrypto";

Object.defineProperty(globalThis, "crypto", {
Expand All @@ -15,67 +11,23 @@ Object.defineProperty(globalThis, "crypto", {
});

test("correctly converts turnkey API key to JWK", async function () {
for (let i = 0; i < 10000; i++) {
try {
const newApiKeyPair = generateP256KeyPair();

const content = crypto.randomBytes(16).toString("hex");

const signed = await signWeb({
content,
publicKey: newApiKeyPair.publicKey,
// publicKey: "",
privateKey:
"ee05fc3bdf4161bc70701c221d8d77180294cefcfcea64ba83c4d4c732fcb9",
});

const result = convertTurnkeyApiKeyToJwk({
uncompressedPrivateKeyHex:
"ee05fc3bdf4161bc70701c221d8d77180294cefcfcea64ba83c4d4c732fcb9", // arbitrary 31 byte hex string
compressedPublicKeyHex: newApiKeyPair.publicKey,
});

const info = {
publicKey: newApiKeyPair.publicKeyUncompressed,
publicKeyBuffer: new Uint8Array(
Buffer.from(newApiKeyPair.publicKeyUncompressed, "hex")
),
publicKeyX: new Uint8Array(
Buffer.from(newApiKeyPair.publicKeyUncompressed, "hex").subarray(
1,
33
)
),
publicKeyXFromHex: uint8ArrayFromHex(
newApiKeyPair.publicKeyUncompressed.slice(2, 66)
),
// publicKeyXLength: new Uint8Array(Buffer.from(newApiKeyPair.publicKeyUncompressed, "hex").subarray(1, 33)).length,
publicKeyY: new Uint8Array(
Buffer.from(newApiKeyPair.publicKeyUncompressed, "hex").subarray(33)
),
publicKeyYFromHex: uint8ArrayFromHex(
newApiKeyPair.publicKeyUncompressed.slice(66)
),
// publicKeyYLength: new Uint8Array(Buffer.from(newApiKeyPair.publicKeyUncompressed, "hex").subarray(33)).length,
};

// console.log(info)

if (info.publicKeyX[0] == 0 || info.publicKeyY[0] == 0) {
console.log("eureka");
console.log("info", info);
}
} catch (err: any) {
console.log("caught an error", err);

throw new Error(err);

// expect(err).toBeTruthy();

// return;
}
}
const content = crypto.randomBytes(16).toString("hex");
const privateKey =
"ee05fc3bdf4161bc70701c221d8d77180294cefcfcea64ba83c4d4c732fcb9"; // 31 bytes, not 32
const publicKey =
"03f3e1d85243f8b2927106cc0ddd84752c7782f863f303f975c3e8fe13d588d534";

expect(
convertTurnkeyApiKeyToJwk({
uncompressedPrivateKeyHex: privateKey,
compressedPublicKeyHex: publicKey,
})
).toBeTruthy();
expect(
await signWeb({
content,
publicKey,
privateKey,
})
).toBeTruthy();
});

const uint8ArrayFromHex = (hexString: string) =>
new Uint8Array(hexString.match(/../g)!.map((h) => parseInt(h, 16)));
7 changes: 0 additions & 7 deletions packages/api-key-stamper/src/tink/elliptic_curves.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ function byteArrayToInteger(bytes: Uint8Array): bigint {

/** Converts bigint to byte array. */
function integerToByteArray(i: bigint, length: number): Uint8Array {
console.log("bigint", i);

const input = i.toString(16);
const numHexChars = length * 2;
let padding = "";
Expand All @@ -49,11 +47,6 @@ function integerToByteArray(i: bigint, length: number): Uint8Array {
} else {
padding = "0".repeat(numHexChars - input.length);
}

console.log("hex input", input);
console.log("input", Bytes.fromHex(input));
console.log("padded input", Bytes.fromHex(padding + input));

return Bytes.fromHex(padding + input);
}

Expand Down

0 comments on commit d531b43

Please sign in to comment.