This commit is contained in:
Josh Mandel 2020-04-20 09:19:32 -05:00
Родитель 4690def21e
Коммит 5beec7b3df
11 изменённых файлов: 74 добавлений и 47 удалений

3
.gitignore поставляемый
Просмотреть файл

@ -1 +1,2 @@
node_modules
node_modules
dist

Просмотреть файл

@ -9,6 +9,8 @@
"scripts": {
"dev": "nodemon --exec ts-node ./src/server.ts",
"dev-ui": "npm run qr-static && parcel watch ./src/*.html --out-dir dist/static",
"lint-ui": "tslint -c tslint.json -p tsconfig.ui.json",
"lint": "tslint -c tslint.json -p tsconfig.json",
"qr-static": "cp node_modules/qr-scanner/qr-scanner-worker.min.js* dist/static",
"build-ui": "npm run qr-static && parcel build ./src/*.html --out-dir dist/static",
"build": "tsc",

Просмотреть файл

@ -1,7 +1,7 @@
export let serverBase = process.env.SERVER_BASE || 'http://localhost:8080/api';
if (serverBase === "relative") {
serverBase = window.location.origin + '/api'
if (serverBase === 'relative') {
serverBase = window.location.origin + '/api';
}
export const resolveUrl = `${serverBase}/did/`;
console.log("SERVER base", process.env, process.env.SERVER_BASE)
console.log('SERVER base', process.env, process.env.SERVER_BASE);

Просмотреть файл

@ -22,7 +22,7 @@ export async function encryptFor (jws: string, did: string, ek: EncryptionKey) {
const resolveKeyId = async (kid: string): Promise<JsonWebKey> => {
const fragment = '#' + kid.split('#')[1];
const didDoc = (await axios.get(resolveUrl + kid)).data;
return didDoc.publicKey.filter(k => k.id == fragment)[0].publicKeyJwk;
return didDoc.publicKey.filter(k => k.id === fragment)[0].publicKeyJwk;
};
export async function generateDid ({ signingPublicKey, encryptionPublicKey }) {
const recoveryPublicKey = signingPublicKey;

Просмотреть файл

@ -1,4 +1,4 @@
export const sampleVc = {
export const sampleVc = {
'@context': [
'https://www.w3.org/2018/credentials/v1'
],

Просмотреть файл

@ -32,7 +32,9 @@ interface HolderState {
}
const initializeHolder = async (simulated: boolean): Promise<HolderState> => {
let ek = await generateEncryptionKey(), sk = await generateSigningKey(), did = await generateDid({
const ek = await generateEncryptionKey();
const sk = await generateSigningKey();
const did = await generateDid({
encryptionPublicKey: ek.publicJwk,
signingPublicKey: sk.publicJwk
});
@ -60,7 +62,7 @@ async function scanOneCode (): Promise<string> {
console.log('Scanning in', videoElement);
let qrScanner = new QrScanner(videoElement, result => {
console.log('decoded qr code:', result);
if (!result.length) {return;}
if (!result.length) { return; }
qrScanner.destroy();
qrScanner = null;
resolve(result);

Просмотреть файл

@ -67,7 +67,9 @@ export async function generateEncryptionKey (input?: JsonWebKey): Promise<Encryp
};
}
export async function generateSigningKey (input?: JsonWebKey): Promise<SigningKey> {
let publicKey, privateKey, publicJwk;
let publicKey;
let privateKey;
let publicJwk;
if (input) {
let uncompressed = new Uint8Array(Buffer.from([0x04, ...base64url.toBuffer(input.x), ...base64url.toBuffer(input.y)]));
publicKey = Buffer.from(uncompressed);

Просмотреть файл

@ -9,8 +9,6 @@ import Did from '../sidetree/lib/core/versions/latest/Did';
import DocumentComposer from '../sidetree/lib/core/versions/latest/DocumentComposer';
import OperationProcessor from '../sidetree/lib/core/versions/latest/OperationProcessor';
const app = express();
app.use(express.raw({ type: 'application/x-www-form-urlencoded' }));
app.use(express.json({ type: 'application/json' }));
@ -94,7 +92,7 @@ app.get('/api/did/:did', async (req, res) => {
});
app.use(express.static('dist/static', {
extensions: ['html'],
extensions: ['html']
}));
// start the Express server

Просмотреть файл

@ -6,16 +6,16 @@ import { serverBase } from './config';
import { generateDid, verifyJws } from './dids';
import { EncryptionKey, generateEncryptionKey, generateSigningKey, SigningKey } from './keys';
import QRCode from 'qrcode'
import QRCode from 'qrcode';
export async function verifierWorld(simulated: boolean) {
export async function verifierWorld (simulated: boolean) {
let state = await initializeVerifier(simulated);
const event = async (e) => {
const pre = state;
state = await verifierEvent(state, e);
console.log("Verifier Event", e.type, e, state);
console.log('Verifier Event', e.type, e, state);
};
console.log("Verifier initial state", state);
console.log('Verifier initial state', state);
await prepareSiopRequest(state, event);
await receiveSiopResponse(state, event);
}
@ -49,10 +49,12 @@ interface VerifierState {
idTokenRaw: string;
idTokenDecrypted: string;
idTokenVerified: any;
}
};
}
const initializeVerifier = async (simulated: boolean): Promise<VerifierState> => {
let ek = await generateEncryptionKey(), sk = await generateSigningKey(), did = await generateDid({
const ek = await generateEncryptionKey();
const sk = await generateSigningKey();
const did = await generateDid({
encryptionPublicKey: ek.publicJwk,
signingPublicKey: sk.publicJwk
});
@ -60,50 +62,50 @@ const initializeVerifier = async (simulated: boolean): Promise<VerifierState> =>
simulated,
ek,
sk,
did,
did
};
};
async function verifierEvent(state: VerifierState, event: any): Promise<VerifierState> {
if (event.type === "siop-request-created") {
async function verifierEvent (state: VerifierState, event: any): Promise<VerifierState> {
if (event.type === 'siop-request-created') {
return { ...state, siopRequest: event.siopRequest };
}
if (event.type === "siop-response-received") {
if (event.type === 'siop-response-received') {
return { ...state, siopResponse: event.siopResponse };
}
return state;
}
async function prepareSiopRequest(state: VerifierState, event: (e: any) => Promise<void>) {
async function prepareSiopRequest (state: VerifierState, event: (e: any) => Promise<void>) {
const siopState = base64url.encode(crypto.randomBytes(16));
const siopRequestHeader = {
kid: state.did + '#signing-key-1'
};
const siopRequestBody = {
state: siopState,
"iss": state.did,
"response_type": "id_token",
"client_id": `${serverBase}/siop`,
"scope": "did_authn",
"response_mode": "form_post",
"nonce": base64url.encode(crypto.randomBytes(16)),
"registration": {
"id_token_signed_response_alg": ["ES256K"],
"client_uri": serverBase
'iss': state.did,
'response_type': 'id_token',
'client_id': `${serverBase}/siop`,
'scope': 'did_authn',
'response_mode': 'form_post',
'nonce': base64url.encode(crypto.randomBytes(16)),
'registration': {
'id_token_signed_response_alg': ['ES256K'],
'client_uri': serverBase
}
};
const siopRequest = await state.sk.sign(siopRequestHeader, siopRequestBody);
const siopRequestCreated = await axios.post(`${serverBase}/siop/begin`, {
siopRequest,
siopRequest
});
const siopRequestQrCodeUrl = 'openid://?' + qs.encode({
response_type: "id_token",
scope: "did_authn",
response_type: 'id_token',
scope: 'did_authn',
request_uri: serverBase + '/siop/' + siopRequestBody.state,
client_id: siopRequestBody.client_id
});
await event({
type: "siop-request-created",
type: 'siop-request-created',
siopRequest: {
payload: siopRequestBody,
jwt: siopRequest,
@ -113,20 +115,20 @@ async function prepareSiopRequest(state: VerifierState, event: (e: any) => Promi
});
if (state.simulated) {
simulatedInteractions.push({
"type": "display-qr-code",
"who": "verifier",
"url": siopRequestQrCodeUrl
'type': 'display-qr-code',
'who': 'verifier',
'url': siopRequestQrCodeUrl
});
} else {
const canvas = document.getElementById('qrcode-canvas')
QRCode.toCanvas(canvas, siopRequestQrCodeUrl, { scale: 20 }, function (error) {
if (error) console.error(error)
const canvas = document.getElementById('qrcode-canvas');
QRCode.toCanvas(canvas, siopRequestQrCodeUrl, { scale: 20 }, (error) => {
if (error) console.error(error);
console.log('success!');
})
});
}
}
async function receiveSiopResponse(state: VerifierState, event: (e: any) => Promise<void>) {
async function receiveSiopResponse (state: VerifierState, event: (e: any) => Promise<void>) {
const POLLING_RATE_MS = 500; // Obviously replace this with websockets, SSE, etc
let responseRetrieved;
do {
@ -139,7 +141,7 @@ async function receiveSiopResponse(state: VerifierState, event: (e: any) => Prom
if (idTokenVerified.valid) {
const idToken = idTokenVerified.payload;
await event({
type: "siop-response-received",
type: 'siop-response-received',
siopResponse: {
idTokenRaw: idTokenRetrieved,
idTokenDecrypted: idTokenRetrievedDecrypted,

18
tsconfig.ui.json Normal file
Просмотреть файл

@ -0,0 +1,18 @@
{
"compilerOptions": {
"module": "commonjs",
"esModuleInterop": true,
"target": "es6",
"noImplicitAny": false,
"moduleResolution": "node",
"sourceMap": true,
"outDir": "dist",
"baseUrl": ".",
"paths": { },
"resolveJsonModule": true,
},
"include": [
"src"
]
}

Просмотреть файл

@ -2,7 +2,8 @@
"extends": "tslint-config-standard",
"linterOptions": {
"exclude": [
"node_modules/**"
"node_modules/**",
"sidetree/**"
]
},
"defaultSeverity": "error",
@ -43,6 +44,7 @@
"only-arrow-functions": [
true,
"allow-named-functions"
]
],
"await-promise": [false]
}
}