Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | 1x 1x 1x 2x 1x 1x 1x 1x 1x 1x 31x 31x 31x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x | import {
encryptECIES,
getPublicKey,
publicKeyToStxAddress,
TokenSigner,
} from 'micro-stacks/crypto';
import { bytesToHex, hexToBytes, utf8ToBytes } from 'micro-stacks/common';
export function makeDIDFromAddress(address: string) {
return `did:btc-addr:${address}`;
}
export function nextMonth() {
return new Date(new Date().setMonth(new Date().getMonth() + 1));
}
export function makeUUID4() {
let d = new Date().getTime();
Iif (typeof performance !== 'undefined' && typeof performance.now === 'function') {
d += performance.now(); // use high-precision timer if available
}
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
const r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16);
});
}
interface MakeAuthResponseParams {
privateKey: string;
profile?: any;
username?: string;
metadata?: any;
coreToken?: string;
appPrivateKey?: string;
expiresAt?: number;
transitPublicKey?: string;
hubUrl?: string;
blockstackAPIUrl?: string;
associationToken?: string;
}
export async function encryptPrivateKey(publicKey: string, privateKey: string): Promise<string> {
const encryptedObj = await encryptECIES({
content: hexToBytes(privateKey),
publicKey,
cipherTextEncoding: 'hex',
wasString: false,
});
const encryptedJSON = JSON.stringify(encryptedObj);
return bytesToHex(utf8ToBytes(encryptedJSON));
}
export async function makeAuthResponse(params: MakeAuthResponseParams): Promise<string> {
let { expiresAt } = params;
const {
privateKey,
appPrivateKey,
coreToken,
transitPublicKey,
metadata,
hubUrl,
blockstackAPIUrl,
associationToken,
username,
profile,
} = params;
/* Convert the private key to a public key to an issuer */
const publicKey = bytesToHex(getPublicKey(privateKey));
const address = publicKeyToStxAddress(publicKey);
if (!expiresAt) expiresAt = nextMonth().getTime() as number;
/* See if we should encrypt with the transit key */
let privateKeyPayload = appPrivateKey;
let coreTokenPayload = coreToken;
let additionalProperties = {};
Iif (appPrivateKey !== undefined && appPrivateKey !== null) {
Iif (transitPublicKey !== undefined && transitPublicKey !== null) {
privateKeyPayload = await encryptPrivateKey(transitPublicKey, appPrivateKey);
Iif (coreToken !== undefined && coreToken !== null) {
coreTokenPayload = await encryptPrivateKey(transitPublicKey, coreToken);
}
}
additionalProperties = {
email: metadata?.email ? metadata.email : null,
profile_url: metadata?.profileUrl ? metadata.profileUrl : null,
hubUrl,
blockstackAPIUrl,
associationToken,
version: 'undefined',
};
}
/* Create the payload */
const payload = {
jti: makeUUID4(),
iat: Math.floor(new Date().getTime() / 1000), // JWT times are in seconds
exp: Math.floor(expiresAt / 1000), // JWT times are in seconds
iss: makeDIDFromAddress(address),
private_key: privateKeyPayload ?? null,
public_keys: [publicKey],
profile: profile ?? null,
username: username ?? null,
core_token: coreTokenPayload ?? null,
...additionalProperties,
};
/* Sign and return the token */
const tokenSigner = new TokenSigner('ES256k', privateKey);
return tokenSigner.sign(payload);
}
|