diff --git a/src/app/approve/approve.component.ts b/src/app/approve/approve.component.ts index a09fa09..f87f4ac 100644 --- a/src/app/approve/approve.component.ts +++ b/src/app/approve/approve.component.ts @@ -3,7 +3,7 @@ import {ActivatedRoute} from '@angular/router'; import {IdentityService} from '../identity.service'; import {AccountService} from '../account.service'; import {GlobalVarsService} from '../global-vars.service'; -import {SigningService} from '../signing.service'; +// import {SigningService} from '../signing.service'; import {BackendAPIService, User} from '../backend-api.service'; import {Observable, of} from 'rxjs'; import {map} from 'rxjs/operators'; @@ -51,7 +51,7 @@ export class ApproveComponent implements OnInit { private identityService: IdentityService, private accountService: AccountService, public globalVars: GlobalVarsService, - private signingService: SigningService, + // private signingService: SigningService, private backendApi: BackendAPIService, ) { } @@ -77,9 +77,11 @@ export class ApproveComponent implements OnInit { onSubmit(): void { // TODO throw "replace all of this transaction parsing and checking with bitcoinjs-lib." + /* const seedHex = "" const signedTransactionHex = this.signingService.signTransaction(seedHex, this.transactionHex); this.finishFlow(signedTransactionHex); + */ } finishFlow(signedTransactionHex?: string): void { diff --git a/src/app/identity.service.ts b/src/app/identity.service.ts index d6151d7..fbcc90a 100644 --- a/src/app/identity.service.ts +++ b/src/app/identity.service.ts @@ -7,30 +7,6 @@ import {GlobalVarsService} from './global-vars.service'; import {CookieService} from 'ngx-cookie'; import {SigningService} from './signing.service'; import {HttpParams} from '@angular/common/http'; -import { - Transaction, - TransactionMetadataBasicTransfer, - TransactionMetadataBitcoinExchange, - TransactionMetadataCreatorCoin, - TransactionMetadataCreatorCoinTransfer, - TransactionMetadataFollow, - TransactionMetadataLike, - TransactionMetadataPrivateMessage, - TransactionMetadataSubmitPost, - TransactionMetadataSwapIdentity, - TransactionMetadataUpdateBitcoinUSDExchangeRate, - TransactionMetadataUpdateGlobalParams, - TransactionMetadataUpdateProfile, - TransactionMetadataNFTTransfer, - TransactionMetadataAcceptNFTTransfer, - TransactionMetadataBurnNFT, - TransactionMetadataNFTBid, - TransactionMetadataAcceptNFTBid, - TransactionMetadataUpdateNFT, - TransactionMetadataCreateNFT, - TransactionMetadataDAOCoin, - TransactionMetadataTransferDAOCoin -} from '../lib/deso/transaction'; @Injectable({ providedIn: 'root' @@ -89,11 +65,14 @@ export class IdentityService { // Incoming Messages private handleSign(data: any): void { - const { id, payload: { encryptedSeedHex, transactionHex } } = data; + // TODO + throw "implement for lbry" + /* + const transaction or action details = data; // This will tell us whether we need full signing access or just ApproveLarge // level of access. - const requiredAccessLevel = this.getRequiredAccessLevel(transactionHex); + const requiredAccessLevel = this.getRequiredAccessLevel(transaction or action details); // In the case that approve() fails, it responds with a message indicating // that approvalRequired = true, which the caller can then uses to trigger @@ -102,21 +81,18 @@ export class IdentityService { return; } - // If we get to this point, no approval UI was required. This typically - // happens if the caller has full signing access or signing access for - // non-spending txns such as like, post, update profile, etc. In the - // latter case we need a subsequent check to ensure that the txn is not - // sending money to any public keys other than the sender himself. - if (!this.approveSpending(data)) { - return; - } - - const seedHex = this.cryptoService.decryptSeedHex(encryptedSeedHex, this.globalVars.hostname); - const signedTransactionHex = this.signingService.signTransaction(seedHex, transactionHex); + // TODO - this.signingService.signPSBT instead + if it's a transaction + const signedTransactionHex = this.signingService.signPSBT(transaction details); + else // just an action + const signedActionHex = this.signingService.signActiov(action details); + // TODO figure this out... this.respond(id, { signedTransactionHex, + signedActionHex, }); + */ } private handleJwt(data: any): void { @@ -163,42 +139,12 @@ export class IdentityService { }); } - // Access levels - private getRequiredAccessLevel(transactionHex: string): AccessLevel { - const txBytes = new Buffer(transactionHex, 'hex'); - const transaction = Transaction.fromBytes(txBytes)[0] as Transaction; - - switch (transaction.metadata.constructor) { - case TransactionMetadataBasicTransfer: - case TransactionMetadataBitcoinExchange: - case TransactionMetadataUpdateBitcoinUSDExchangeRate: - case TransactionMetadataCreatorCoin: - case TransactionMetadataCreatorCoinTransfer: - case TransactionMetadataSwapIdentity: - case TransactionMetadataUpdateGlobalParams: - case TransactionMetadataUpdateProfile: - case TransactionMetadataCreateNFT: - case TransactionMetadataUpdateNFT: - case TransactionMetadataAcceptNFTBid: - case TransactionMetadataNFTBid: - case TransactionMetadataNFTTransfer: - case TransactionMetadataAcceptNFTTransfer: - case TransactionMetadataBurnNFT: - case TransactionMetadataDAOCoin: - case TransactionMetadataTransferDAOCoin: - return AccessLevel.Full; - - case TransactionMetadataFollow: - case TransactionMetadataPrivateMessage: - case TransactionMetadataSubmitPost: - case TransactionMetadataLike: - return AccessLevel.ApproveLarge; - } - - return AccessLevel.Full; - } + // TODO implement for lbry + // private getRequiredAccessLevel(transactionHex: string): AccessLevel { + // switch case on the type of transaction or action, and return the required access level + // unless required access level is going to be case by case for each user private hasAccessLevel(data: any, requiredAccessLevel: AccessLevel): boolean { const { payload: { encryptedSeedHex, accessLevel, accessLevelHmac }} = data; @@ -210,25 +156,6 @@ export class IdentityService { return this.cryptoService.validAccessLevelHmac(accessLevel, seedHex, accessLevelHmac); } - // This method checks if transaction in the payload has correct outputs for requested AccessLevel. - private approveSpending(data: any): boolean { - const { payload: { accessLevel, transactionHex }} = data; - - // If the requested access level is ApproveLarge, we want to confirm that transaction doesn't - // attempt sending $DESO to a non-owner public key. If it does, we respond with approvalRequired. - if (accessLevel === AccessLevel.ApproveLarge) { - const txBytes = new Buffer(transactionHex, 'hex'); - const transaction = Transaction.fromBytes(txBytes)[0] as Transaction; - for (const output of transaction.outputs) { - if (output.publicKey.toString('hex') !== transaction.publicKey.toString('hex')) { - this.respond(data.id, {approvalRequired: true}); - return false; - } - } - } - return true; - } - private approve(data: any, accessLevel: AccessLevel): boolean { const hasAccess = this.hasAccessLevel(data, accessLevel); const hasEncryptionKey = this.cryptoService.hasSeedHexEncryptionKey(this.globalVars.hostname); diff --git a/src/app/signing.service.ts b/src/app/signing.service.ts index bd4bd5d..fce9751 100644 --- a/src/app/signing.service.ts +++ b/src/app/signing.service.ts @@ -1,9 +1,6 @@ import { Injectable } from '@angular/core'; import KeyEncoder from 'key-encoder'; import * as jsonwebtoken from 'jsonwebtoken'; -import {CryptoService} from './crypto.service'; -import * as sha256 from 'sha256'; -import { uvarint64ToBuf } from '../lib/bindata/util'; import * as bip32 from 'bip32'; import { BIP32Interface } from 'bip32'; // TODO: Installed 2.0.6 instead of latest version, only because of weird typescript compilation stuff. Should probably get the latest. @@ -18,9 +15,7 @@ const NETWORK = lbry.networks.mainnet }) export class SigningService { - constructor( - private cryptoService: CryptoService, - ) { } + constructor() { } // this should be audited and go into a library. hobbled this together from // code in bitcoinjs-lib. @@ -75,39 +70,29 @@ export class SigningService { } signJWT(seedHex: string): string { + return "" + + // TODO - use bitcoinjs-lib and do an actual signature with the actual key in the wallet, send the identifier of the wallet over, etc etc etc. + // Assuming we want to keep this + const keyEncoder = new KeyEncoder('secp256k1'); const encodedPrivateKey = keyEncoder.encodePrivate(seedHex, 'raw', 'pem'); return jsonwebtoken.sign({ }, encodedPrivateKey, { algorithm: 'ES256', expiresIn: 60 * 10 }); } signAction(seedHex: string, actionHex: string): string { + return "" + // TODO - use bitcoinjs-lib and do an actual signature with the actual key in the wallet, send the identifier of the wallet over, etc etc etc. + + /* const privateKey = this.cryptoService.seedHexToPrivateKey(seedHex); const actionBytes = new Buffer(actionHex, 'hex'); const actionHash = new Buffer(sha256.x2(actionBytes), 'hex'); const signature = privateKey.sign(actionHash); return new Buffer(signature.toDER()).toString('hex'); - } - - signTransaction(seedHex: string, transactionHex: string): string { - const privateKey = this.cryptoService.seedHexToPrivateKey(seedHex); - - const transactionBytes = new Buffer(transactionHex, 'hex'); - const transactionHash = new Buffer(sha256.x2(transactionBytes), 'hex'); - const signature = privateKey.sign(transactionHash); - const signatureBytes = new Buffer(signature.toDER()); - const signatureLength = uvarint64ToBuf(signatureBytes.length); - - const signedTransactionBytes = Buffer.concat([ - // This slice is bad. We need to remove the existing signature length field prior to appending the new one. - // Once we have frontend transaction construction we won't need to do this. - transactionBytes.slice(0, -1), - signatureLength, - signatureBytes, - ]); - - return signedTransactionBytes.toString('hex'); + */ } }