Add pgp signer.
This commit is contained in:
parent
9d2fdd687b
commit
7165031fc8
@ -34,6 +34,7 @@
|
||||
"mocha": "^8.2.1",
|
||||
"moolb": "^0.1.0",
|
||||
"ng2-charts": "^2.4.2",
|
||||
"openpgp": "^4.10.10",
|
||||
"popper.js": "^1.16.1",
|
||||
"rxjs": "~6.6.0",
|
||||
"tslib": "^2.0.0",
|
||||
|
@ -3,3 +3,5 @@ export * from './array-sum';
|
||||
export * from './accountIndex';
|
||||
export * from './custom-error-state-matcher';
|
||||
export * from './http-getter';
|
||||
export * from './pgp-signer';
|
||||
|
||||
|
8
src/app/_helpers/pgp-signer.spec.ts
Normal file
8
src/app/_helpers/pgp-signer.spec.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { PGPSigner } from './pgp-signer';
|
||||
let keystore;
|
||||
|
||||
describe('PgpSigner', () => {
|
||||
it('should create an instance', () => {
|
||||
expect(new PGPSigner(keystore)).toBeTruthy();
|
||||
});
|
||||
});
|
102
src/app/_helpers/pgp-signer.ts
Normal file
102
src/app/_helpers/pgp-signer.ts
Normal file
@ -0,0 +1,102 @@
|
||||
const openpgp = require('openpgp');
|
||||
|
||||
interface Signable {
|
||||
digest(): string;
|
||||
}
|
||||
|
||||
type Signature = {
|
||||
engine: string
|
||||
algo: string
|
||||
data: string
|
||||
digest: string;
|
||||
};
|
||||
|
||||
interface Signer {
|
||||
onsign(signature: Signature): void;
|
||||
onverify(flag: boolean): void;
|
||||
fingerprint(): string;
|
||||
prepare(material: Signable): boolean;
|
||||
verify(digest: string, signature: Signature): void;
|
||||
sign(digest: string): void;
|
||||
}
|
||||
|
||||
class PGPSigner implements Signer {
|
||||
|
||||
engine = 'pgp';
|
||||
algo = 'sha256';
|
||||
dgst: string;
|
||||
signature: Signature;
|
||||
keyStore;
|
||||
onsign: (signature: Signature) => void;
|
||||
onverify: (flag: boolean) => void;
|
||||
|
||||
constructor(keyStore) {
|
||||
this.keyStore = keyStore;
|
||||
this.onsign = (signature: Signature) => {};
|
||||
this.onverify = (flag: boolean) => {};
|
||||
}
|
||||
|
||||
public fingerprint(): string {
|
||||
return this.keyStore.getFingerprint();
|
||||
}
|
||||
|
||||
public prepare(material: Signable): boolean {
|
||||
this.dgst = material.digest();
|
||||
return true;
|
||||
}
|
||||
|
||||
public verify(digest: string, signature: Signature): void {
|
||||
openpgp.signature.readArmored(signature.data).then((sig) => {
|
||||
const opts = {
|
||||
message: openpgp.cleartext.fromText(digest),
|
||||
publicKeys: this.keyStore.getTrustedKeys(),
|
||||
signature: sig,
|
||||
};
|
||||
openpgp.verify(opts).then((v) => {
|
||||
let i = 0;
|
||||
for (i = 0; i < v.signatures.length; i++) {
|
||||
const s = v.signatures[i];
|
||||
if (s.valid) {
|
||||
this.onverify(s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
console.error('checked ' + i + ' signature(s) but none valid');
|
||||
this.onverify(false);
|
||||
});
|
||||
}).catch((e) => {
|
||||
console.error(e);
|
||||
this.onverify(false);
|
||||
});
|
||||
}
|
||||
|
||||
public sign(digest: string): void {
|
||||
const m = openpgp.cleartext.fromText(digest);
|
||||
const pk = this.keyStore.getPrivateKey();
|
||||
const opts = {
|
||||
message: m,
|
||||
privateKeys: [pk],
|
||||
detached: true,
|
||||
};
|
||||
openpgp.sign(opts).then((s) => {
|
||||
this.signature = {
|
||||
engine: this.engine,
|
||||
algo: this.algo,
|
||||
data: s.signature,
|
||||
// TODO: fix for browser later
|
||||
digest,
|
||||
};
|
||||
this.onsign(this.signature);
|
||||
}).catch((e) => {
|
||||
console.error(e);
|
||||
this.onsign(undefined);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
Signable,
|
||||
Signature,
|
||||
Signer,
|
||||
PGPSigner
|
||||
};
|
@ -3,12 +3,17 @@ import {BehaviorSubject, Observable, of} from 'rxjs';
|
||||
import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http';
|
||||
import {environment} from '../../environments/environment';
|
||||
import {first, map} from 'rxjs/operators';
|
||||
import { Envelope, Syncable } from '../../assets/js/cic-meta/sync.js';
|
||||
import { ArgPair, Envelope, Syncable } from '../../assets/js/cic-meta/sync.js';
|
||||
import {PGPSigner, Signer} from '../_helpers';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class UserService {
|
||||
keystore = '';
|
||||
syncableAccount: Syncable;
|
||||
signer: Signer = new PGPSigner(this.keystore);
|
||||
|
||||
accounts: any = '';
|
||||
private accountsList = new BehaviorSubject<any>(this.accounts);
|
||||
accountsSubject = this.accountsList.asObservable();
|
||||
@ -48,9 +53,9 @@ export class UserService {
|
||||
);
|
||||
}
|
||||
|
||||
changeAccountInfo(address: string, status: string, name: string, phoneNumber: string, type: string, token: string,
|
||||
failedPinAttempts: string, bio: string, gender: string, businessCategory: string, userLocation: string,
|
||||
location: string, referrer: string): Observable<any> {
|
||||
async changeAccountInfo(address: string, status: string, name: string, phoneNumber: string, type: string, token: string,
|
||||
failedPinAttempts: string, bio: string, gender: string, businessCategory: string, userLocation: string,
|
||||
location: string, referrer: string): Promise<any> {
|
||||
const accountDetails = {
|
||||
status,
|
||||
name,
|
||||
@ -65,20 +70,32 @@ export class UserService {
|
||||
location,
|
||||
referrer
|
||||
};
|
||||
const addressStub = address.slice(2);
|
||||
const headers = new HttpHeaders().append('x-cic-automerge', 'client');
|
||||
this.http.get(`${environment.cicMetaUrl}/${addressStub}`, { headers }).pipe(first()).subscribe(res => {
|
||||
console.log(res);
|
||||
const response = Envelope.fromJSON(res);
|
||||
response.unwrap();
|
||||
console.log(response);
|
||||
}, error => {
|
||||
let addressStub = address.slice(2);
|
||||
addressStub = '0000000000000000000000000000000000000000000000000000000000000000';
|
||||
const headers = new HttpHeaders({'x-cic-automerge': 'client'});
|
||||
this.http.get(`${environment.cicMetaUrl}/${addressStub}`, { headers }).pipe(first()).subscribe(async res => {
|
||||
this.syncableAccount = Envelope.fromJSON(res).unwrap();
|
||||
let update = [];
|
||||
for (const prop in accountDetails) {
|
||||
update.push(new ArgPair(prop, accountDetails[prop]));
|
||||
}
|
||||
this.syncableAccount.update(update, 'client-branch');
|
||||
await this.updateMeta(addressStub, headers);
|
||||
}, async error => {
|
||||
console.error('There is an error!', error);
|
||||
const refName = addressStub + ':cic-person';
|
||||
this.syncableAccount = new Syncable(refName, accountDetails);
|
||||
await this.updateMeta(addressStub, headers);
|
||||
});
|
||||
this.http.put(`${environment.cicMetaUrl}/${addressStub}`, { data: accountDetails }, { headers }).pipe(first()).subscribe(res => {
|
||||
return addressStub;
|
||||
}
|
||||
|
||||
async updateMeta(addressStub: string, headers: HttpHeaders): Promise<any> {
|
||||
const envelope = await this.wrap(this.syncableAccount , this.signer);
|
||||
const reqBody = envelope.toJSON();
|
||||
this.http.put(`${environment.cicMetaUrl}/${addressStub}`, { data: reqBody }, { headers }).pipe(first()).subscribe(res => {
|
||||
console.log(res);
|
||||
});
|
||||
return of(addressStub);
|
||||
}
|
||||
|
||||
getAccounts(): void {
|
||||
@ -136,4 +153,18 @@ export class UserService {
|
||||
return response;
|
||||
}));
|
||||
}
|
||||
|
||||
wrap(syncable: Syncable, signer: Signer): Promise<Envelope> {
|
||||
return new Promise<Envelope>((whohoo, doh) => {
|
||||
syncable.setSigner(signer);
|
||||
syncable.onwrap = async (env) => {
|
||||
if (env === undefined) {
|
||||
doh();
|
||||
return;
|
||||
}
|
||||
whohoo(env);
|
||||
};
|
||||
syncable.sign();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -219,14 +219,14 @@
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<button mat-raised-button color="warn" type="button" class="btn btn-outline-danger">
|
||||
<button mat-raised-button color="warn" type="button" class="btn btn-outline-danger mb-3">
|
||||
Delete User
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<button mat-raised-button color="primary" type="submit" class="btn btn-outline-primary ml-2">
|
||||
SAVE
|
||||
<button mat-raised-button color="primary" type="submit" class="btn btn-outline-primary">
|
||||
SAVE DETAILS
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -172,9 +172,7 @@ export class AccountDetailsComponent implements OnInit {
|
||||
this.accountInfoFormStub.userLocation.value,
|
||||
this.accountInfoFormStub.location.value,
|
||||
this.accountInfoFormStub.referrer.value,
|
||||
).pipe(first()).subscribe(res => {
|
||||
console.log(res);
|
||||
});
|
||||
).then(res => console.log(res));
|
||||
this.submitted = false;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user