Browse Source

crypto forge impl

user 5 năm trước cách đây
mục cha
commit
16cf4f5710

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 30 - 6
__tests__/crypto.test.ts


+ 1 - 1
__tests__/index.test.ts

@@ -3,7 +3,7 @@ import { BankClient } from '../src/index';
 import { StorageNode } from '../src/storage-node';
 import { IWebClient } from '../src/webclient';
 import { WebClientNode } from '../src/webclient-node';
-import { CryptoNode } from './../src/crypto-node';
+import CryptoNode from './../src/crypto-node';
 import { IWebClientOptions } from './../src/webclient-options';
 
 describe('BankClient', () => {

+ 11 - 0
lib/crypto-forge.d.ts

@@ -0,0 +1,11 @@
+/// <reference types="node" />
+import { ICrypto } from './crypto';
+import { IKeyPair } from './key-pair';
+export default class CryptoForge implements ICrypto {
+    generateRsaKeyPair(bits: number): Promise<IKeyPair>;
+    sign(privateKeyObj: any, data: Buffer): Promise<string>;
+    importRsaKeyPair(serialized: any): Promise<IKeyPair>;
+    private getPublicHash;
+    private getPublicKey;
+    private export;
+}

+ 79 - 0
lib/crypto-forge.js

@@ -0,0 +1,79 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+    return new (P || (P = Promise))(function (resolve, reject) {
+        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
+        step((generator = generator.apply(thisArg, _arguments || [])).next());
+    });
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+    return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const bs58_1 = __importDefault(require("bs58"));
+const node_forge_1 = require("node-forge");
+class CryptoForge {
+    generateRsaKeyPair(bits) {
+        return new Promise((resolve, reject) => {
+            node_forge_1.pki.rsa.generateKeyPair({ bits, workers: 2 }, (err, { privateKey, publicKey }) => {
+                if (err) {
+                    reject(err);
+                    return;
+                }
+                resolve({
+                    export: () => this.export(privateKey, publicKey),
+                    getPublicHash: () => this.getPublicHash(publicKey),
+                    getPublicKey: () => this.getPublicKey(publicKey),
+                    sign: (data) => this.sign(privateKey, data),
+                });
+            });
+        });
+    }
+    sign(privateKeyObj, data) {
+        return __awaiter(this, void 0, void 0, function* () {
+            const sha256 = node_forge_1.md.sha256.create();
+            const buf = node_forge_1.util.hexToBytes(data.toString('hex'));
+            sha256.update(buf);
+            const signature = privateKeyObj.sign(sha256);
+            const hexed = node_forge_1.util.bytesToHex(signature);
+            return hexed;
+        });
+    }
+    importRsaKeyPair(serialized) {
+        return __awaiter(this, void 0, void 0, function* () {
+            const { privateKey, publicKey } = JSON.parse(bs58_1.default.decode(serialized).toString('utf-8'));
+            const privateKeyObj = node_forge_1.pki.privateKeyFromPem(privateKey);
+            const publicKeyObj = node_forge_1.pki.publicKeyFromPem(publicKey);
+            return {
+                export: () => this.export(privateKeyObj, publicKeyObj),
+                getPublicHash: () => this.getPublicHash(publicKeyObj),
+                getPublicKey: () => this.getPublicKey(publicKeyObj),
+                sign: (data) => this.sign(privateKeyObj, data),
+            };
+        });
+    }
+    getPublicHash(publicKeyObj) {
+        const publicKeyHexString = this.getPublicKey(publicKeyObj);
+        const sha256 = node_forge_1.md.sha256.create();
+        const buf = node_forge_1.util.hexToBytes(publicKeyHexString);
+        sha256.update(buf);
+        const digested = sha256.digest().bytes();
+        const pubHash = bs58_1.default.encode(Buffer.from(digested, 'binary'));
+        return pubHash;
+    }
+    getPublicKey(publicKeyObj) {
+        const pk = node_forge_1.asn1.toDer(node_forge_1.pki.publicKeyToAsn1(publicKeyObj)).toHex();
+        return pk;
+    }
+    export(privateKeyObj, publicKeyObj) {
+        return __awaiter(this, void 0, void 0, function* () {
+            const privateKey = node_forge_1.pki.privateKeyToPem(privateKeyObj);
+            const publicKey = node_forge_1.pki.publicKeyToPem(publicKeyObj);
+            const jsonString = JSON.stringify({ privateKey, publicKey });
+            return bs58_1.default.encode(Buffer.from(jsonString, 'utf-8'));
+        });
+    }
+}
+exports.default = CryptoForge;
+//# sourceMappingURL=crypto-forge.js.map

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 0
lib/crypto-forge.js.map


+ 2 - 2
lib/crypto-node.d.ts

@@ -1,9 +1,9 @@
 /// <reference types="node" />
 import { ICrypto } from './crypto';
 import { IKeyPair } from './key-pair';
-export declare class CryptoNode implements ICrypto {
+export default class CryptoNode implements ICrypto {
     generateRsaKeyPair(bits: number): Promise<IKeyPair>;
-    sign(privateKeyText: string, data: Buffer): Promise<Buffer>;
+    sign(privateKeyText: string, data: Buffer): Promise<string>;
     importRsaKeyPair(serialized: string): Promise<IKeyPair>;
     private getPublicHash;
     private getPublicKey;

+ 1 - 1
lib/crypto-node.js

@@ -84,5 +84,5 @@ class CryptoNode {
         });
     }
 }
-exports.CryptoNode = CryptoNode;
+exports.default = CryptoNode;
 //# sourceMappingURL=crypto-node.js.map

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
lib/crypto-node.js.map


+ 1 - 1
lib/index.js

@@ -432,7 +432,7 @@ class BankClient {
                 msg: util_1.encodeHex(messageBytes),
                 pub: util_1.encodeHex(Buffer.from(publicKey, 'hex')),
                 pubHash,
-                sig: util_1.encodeHex(signatureBytes),
+                sig: util_1.encodeHex(Buffer.from(signatureBytes, 'hex')),
             };
             return result;
         });

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
lib/index.js.map


+ 1 - 1
lib/key-pair.d.ts

@@ -2,6 +2,6 @@
 export interface IKeyPair {
     getPublicKey(): string;
     getPublicHash(): string;
-    sign(data: Buffer): Promise<Buffer>;
+    sign(data: Buffer): Promise<string>;
     export(): Promise<string>;
 }

+ 5 - 2
lib/sample.js

@@ -7,13 +7,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
         step((generator = generator.apply(thisArg, _arguments || [])).next());
     });
 };
+var __importDefault = (this && this.__importDefault) || function (mod) {
+    return (mod && mod.__esModule) ? mod : { "default": mod };
+};
 Object.defineProperty(exports, "__esModule", { value: true });
 const index_1 = require("./index");
 const storage_node_1 = require("./storage-node");
 const webclient_node_1 = require("./webclient-node");
 const host = 'http://127.0.0.1:8082';
-const crypto_node_1 = require("./../src/crypto-node");
-const bankClient = new index_1.BankClient(host, 'https://distributing.fun', new storage_node_1.StorageNode('bankClient'), new webclient_node_1.WebClientNode(), new crypto_node_1.CryptoNode());
+const crypto_node_1 = __importDefault(require("./../src/crypto-node"));
+const bankClient = new index_1.BankClient(host, 'https://distributing.fun', new storage_node_1.StorageNode('bankClient'), new webclient_node_1.WebClientNode(), new crypto_node_1.default());
 (() => __awaiter(this, void 0, void 0, function* () {
     yield bankClient.bootstrap();
     const peerId = yield bankClient.getPub();

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
lib/sample.js.map


+ 1 - 1
lib/webclient-node.js

@@ -51,7 +51,7 @@ class WebClientNode {
             if (options.body) {
                 rpOptions.body = options.body;
             }
-            console.log('rpOptions', options, rpOptions);
+            // console.log('rpOptions', options, rpOptions);
             try {
                 const result = yield request(rpOptions);
                 return JSON.parse(result);

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
lib/webclient-node.js.map


+ 28 - 3
package-lock.json

@@ -448,6 +448,15 @@
         "@types/node": "*"
       }
     },
+    "@types/bs58": {
+      "version": "4.0.1",
+      "resolved": "https://npm.bgs.dev/@types%2fbs58/-/bs58-4.0.1.tgz",
+      "integrity": "sha512-yfAgiWgVLjFCmRv8zAcOIHywYATEwiTVccTLnRp6UxTNavT55M9d/uhK3T03St/+8/z/wW+CRjGKUNmEqoHHCA==",
+      "dev": true,
+      "requires": {
+        "base-x": "^3.0.6"
+      }
+    },
     "@types/caseless": {
       "version": "0.12.2",
       "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz",
@@ -560,6 +569,15 @@
       "integrity": "sha512-gojym4tX0FWeV2gsW4Xmzo5wxGjXGm550oVUII7f7G5o4BV6c7DBdiG1RRQd+y1bvqRyYtPfMK85UM95vsapqQ==",
       "dev": true
     },
+    "@types/node-forge": {
+      "version": "0.9.4",
+      "resolved": "https://npm.bgs.dev/@types%2fnode-forge/-/node-forge-0.9.4.tgz",
+      "integrity": "sha512-uFhaKXdhhrLNzfNhXbXJqDwF3jXMzN9qfkdW+IAMnAfwqNZhBcE/cciMITLT0Sg6ls6JYHo3xVWNXAG1g9tm8A==",
+      "dev": true,
+      "requires": {
+        "@types/node": "*"
+      }
+    },
     "@types/range-parser": {
       "version": "1.2.3",
       "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz",
@@ -4183,6 +4201,13 @@
         "rsa-pem-to-jwk": "^1.1.3",
         "tweetnacl": "^1.0.0",
         "ursa-optional": "~0.9.10"
+      },
+      "dependencies": {
+        "node-forge": {
+          "version": "0.7.6",
+          "resolved": "https://npm.bgs.dev/node-forge/-/node-forge-0.7.6.tgz",
+          "integrity": "sha512-sol30LUpz1jQFBjOKwbjxijiE3b6pjd74YwfD0fJOKPjF+fONKb2Yg8rYgS6+bK6VDl+/wfr4IYpC7jDzLUIfw=="
+        }
       }
     },
     "libp2p-crypto-secp256k1": {
@@ -4575,9 +4600,9 @@
       }
     },
     "node-forge": {
-      "version": "0.7.6",
-      "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.6.tgz",
-      "integrity": "sha512-sol30LUpz1jQFBjOKwbjxijiE3b6pjd74YwfD0fJOKPjF+fONKb2Yg8rYgS6+bK6VDl+/wfr4IYpC7jDzLUIfw=="
+      "version": "0.9.1",
+      "resolved": "https://npm.bgs.dev/node-forge/-/node-forge-0.9.1.tgz",
+      "integrity": "sha512-G6RlQt5Sb4GMBzXvhfkeFmbqR6MzhtnT7VTHuLadjkii3rdYHNdw0m8zA4BTxVIh68FicCQ2NSUANpsqkr9jvQ=="
     },
     "node-int64": {
       "version": "0.4.0",

+ 3 - 0
package.json

@@ -15,10 +15,12 @@
   "author": "",
   "license": "ISC",
   "devDependencies": {
+    "@types/bs58": "^4.0.1",
     "@types/express": "^4.17.0",
     "@types/jest": "^24.0.15",
     "@types/nock": "^10.0.3",
     "@types/node": "^12.6.2",
+    "@types/node-forge": "^0.9.4",
     "@types/request-promise": "^4.1.44",
     "@types/ws": "^6.0.1",
     "eslint": "^6.1.0",
@@ -35,6 +37,7 @@
     "bs58": "^4.0.1",
     "express": "^4.17.1",
     "libp2p-crypto": "^0.16.1",
+    "node-forge": "^0.9.1",
     "request": "^2.88.0",
     "request-promise": "^4.2.4",
     "ws": "^7.1.0"

+ 72 - 0
src/crypto-forge.ts

@@ -0,0 +1,72 @@
+import bs58 from 'bs58';
+import { asn1, md, pki, util } from 'node-forge';
+import { ICrypto } from './crypto';
+import { IKeyPair } from './key-pair';
+
+export default class CryptoForge implements ICrypto {
+
+    public generateRsaKeyPair(bits: number): Promise<IKeyPair> {
+        return new Promise((resolve, reject) => {
+            pki.rsa.generateKeyPair({bits, workers: 2}, (err, {privateKey, publicKey}) => {
+                if (err) {
+                    reject(err);
+                    return;
+                }
+
+                resolve({
+                    export: () => this.export(privateKey, publicKey),
+                    getPublicHash: () => this.getPublicHash(publicKey),
+                    getPublicKey: () => this.getPublicKey(publicKey),
+                    sign: (data: Buffer) => this.sign(privateKey, data),
+                });
+              });
+        });
+    }
+
+      public async sign(privateKeyObj: any, data: Buffer): Promise<string> {
+        const sha256 = md.sha256.create();
+        const buf = util.hexToBytes(data.toString('hex'));
+        sha256.update(buf);
+        const signature = privateKeyObj.sign(sha256);
+        const hexed = util.bytesToHex(signature);
+        return hexed;
+      }
+
+      public async importRsaKeyPair(serialized: any): Promise<IKeyPair> {
+        const { privateKey, publicKey } = JSON.parse(bs58.decode(serialized).toString('utf-8'));
+
+        const privateKeyObj = pki.privateKeyFromPem(privateKey);
+        const publicKeyObj = pki.publicKeyFromPem(publicKey);
+
+        return {
+          export: () => this.export(privateKeyObj, publicKeyObj),
+          getPublicHash: () => this.getPublicHash(publicKeyObj),
+          getPublicKey: () => this.getPublicKey(publicKeyObj),
+          sign: (data: Buffer) => this.sign(privateKeyObj, data),
+      };
+    }
+
+      private getPublicHash(publicKeyObj: any): string {
+        const publicKeyHexString = this.getPublicKey(publicKeyObj);
+
+        const sha256 = md.sha256.create();
+        const buf = util.hexToBytes(publicKeyHexString);
+        sha256.update(buf);
+        const digested = sha256.digest().bytes();
+        const pubHash = bs58.encode(Buffer.from(digested, 'binary'));
+        return pubHash;
+      }
+  
+      private getPublicKey(publicKeyObj: any): string {
+        const pk = asn1.toDer(pki.publicKeyToAsn1(publicKeyObj)).toHex();
+        return pk;
+      }
+
+    private async export(privateKeyObj: any, publicKeyObj: any): Promise<string> {
+      const privateKey = pki.privateKeyToPem(privateKeyObj);
+      const publicKey = pki.publicKeyToPem(publicKeyObj);
+
+        const jsonString = JSON.stringify({privateKey, publicKey});
+        return bs58.encode(Buffer.from(jsonString, 'utf-8'));
+    }
+}

+ 2 - 2
src/crypto-node.ts

@@ -5,7 +5,7 @@ const bs58 = require('bs58');
 import { ICrypto } from './crypto';
 import { IKeyPair } from './key-pair';
 
-export class CryptoNode implements ICrypto {
+export default class CryptoNode implements ICrypto {
 
     public generateRsaKeyPair(bits: number): Promise<IKeyPair> {
         return new Promise((resolve, reject) => {
@@ -36,7 +36,7 @@ export class CryptoNode implements ICrypto {
             });
     }
 
-    public async sign(privateKeyText: string, data: Buffer): Promise<Buffer> {
+    public async sign(privateKeyText: string, data: Buffer): Promise<string> {
       const privateKey = createPrivateKey(privateKeyText);
       const sign = createSign('SHA256');
       sign.write(data);

+ 1 - 1
src/index.ts

@@ -432,7 +432,7 @@ export class BankClient {
       msg: encodeHex(messageBytes),
       pub: encodeHex(Buffer.from(publicKey, 'hex')),
       pubHash,
-      sig: encodeHex(signatureBytes),
+      sig: encodeHex(Buffer.from(signatureBytes, 'hex')),
     };
     return result;
   }

+ 1 - 1
src/key-pair.ts

@@ -4,7 +4,7 @@ export interface IKeyPair {
 
     getPublicHash(): string;
 
-    sign(data: Buffer): Promise<Buffer>;
+    sign(data: Buffer): Promise<string>;
 
     export(): Promise<string>;
 

+ 1 - 1
src/sample.ts

@@ -2,7 +2,7 @@ import { BankClient } from './index';
 import { StorageNode } from './storage-node';
 import { WebClientNode } from './webclient-node';
 const host = 'http://127.0.0.1:8082';
-import { CryptoNode } from './../src/crypto-node';
+import CryptoNode from './../src/crypto-node';
 
 const bankClient = new BankClient(host, 'https://distributing.fun', new StorageNode('bankClient'), new WebClientNode(), new CryptoNode());
 

+ 1 - 1
src/webclient-node.ts

@@ -43,7 +43,7 @@ export class WebClientNode implements IWebClient {
         if (options.body) {
             rpOptions.body = options.body;
         }
-        console.log('rpOptions', options, rpOptions);
+        // console.log('rpOptions', options, rpOptions);
         try {
             const result = await request(rpOptions);
             return JSON.parse(result);