123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- import { Injectable } from "@angular/core";
- import { TwitterApiProvider } from "../twitter-api/twitter-api";
- import { P2pStorageIpfsProvider } from "../p2p-storage-ipfs/p2p-storage-ipfs";
- import { Storage } from "@ionic/storage";
- import NodeRSA from "node-rsa";
- @Injectable()
- export class CryptoProvider {
- ownUserId: string;
- constructor(
- private twitter: TwitterApiProvider,
- private ipfs: P2pStorageIpfsProvider,
- private storage: Storage
- ) {
- this.init();
- }
- private async init() {
- this.ownUserId = await this.storage.get("userId");
- }
- public async publishPublicKey(key: string) {
- let publicKeyHistory = await this.getKeyHistory(this.ownUserId);
- // Todo: avoid publishing the same public key twice - check if new key equals newest key in history
- // Add new key to history
- const newKey = {
- key: key,
- validFrom: Date.now()
- };
- if (publicKeyHistory) {
- publicKeyHistory["keys"].push(newKey);
- } else {
- publicKeyHistory = {
- keys: [newKey]
- };
- }
- // Publish updated key history...
- const res = await this.ipfs.storePublicKey(publicKeyHistory);
- // ... and update description in user profile
- this.twitter.updateProfileDescription(
- "ipfs://" + res["Hash"] + " #hybridOSN"
- );
- }
- private async getKeyHistory(userId: string) {
- // Get user description
- const userData = await this.twitter.fetchUser(userId);
- const profileDescription = userData["description"];
- // Extract link to public key
- const link = this.extractLinkFromDescription(profileDescription);
- // Fetch public key history
- if (link.length) {
- return await this.ipfs.fetchJson(link);
- } else {
- return null;
- }
- }
- private extractLinkFromDescription(profileDescription: string): string {
- for (let word of profileDescription.split(" ")) {
- if (this.isLink(word)) {
- return word.substr(7);
- }
- }
- return "";
- }
- private isLink(word: string): boolean {
- const hits = word.match(/ipfs:\/\/Qm[a-zA-Z0-9]+/);
- return hits != null;
- }
- public async generateRsaKeys() {
- return await crypto.subtle.generateKey(
- {
- name: "RSA-OAEP",
- modulusLength: 1024,
- publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
- hash: { name: "SHA-256" }
- },
- true,
- ["encrypt", "decrypt"]
- );
- }
- public async extractPrivateKey(keys): Promise<string> {
- return btoa(
- String.fromCharCode.apply(
- null,
- new Uint8Array(await crypto.subtle.exportKey("pkcs8", keys.privateKey))
- )
- );
- }
- public async extractPublicKey(keys): Promise<string> {
- return btoa(
- String.fromCharCode.apply(
- null,
- new Uint8Array(await crypto.subtle.exportKey("spki", keys.publicKey))
- )
- );
- }
- public async isPublicKeyPublished(): Promise<boolean> {
- const publicKey = await this.storage.get("publicKey");
- const keyHistory = await this.getKeyHistory(this.ownUserId);
- if (keyHistory && publicKey.length) {
- const newestPublicKey = keyHistory["keys"].reverse()[0]["key"];
- return newestPublicKey === publicKey;
- } else {
- return false;
- }
- }
- public async isPrivateKeySet(): Promise<boolean> {
- const privateKey = await this.storage.get("privateKey");
- return privateKey.length > 0;
- }
- public encrypt(plainText: string, privateKey: string) {
- const key = new NodeRSA(
- `-----BEGIN PRIVATE KEY-----${privateKey}-----END PRIVATE KEY-----`
- );
- return key.encryptPrivate(plainText, "base64");
- }
- public decrypt(encryptedMessage: string, publicKey: string): string {
- const key = new NodeRSA(
- `-----BEGIN PUBLIC KEY-----${publicKey}-----END PUBLIC KEY-----`
- );
- return key.decryptPublic(encryptedMessage).toString();
- }
- }
|