Remove some stuff we wont need in signing and identity service
This commit is contained in:
parent
a761ba1a06
commit
970c0e68e7
3 changed files with 32 additions and 118 deletions
|
@ -3,7 +3,7 @@ import {ActivatedRoute} from '@angular/router';
|
||||||
import {IdentityService} from '../identity.service';
|
import {IdentityService} from '../identity.service';
|
||||||
import {AccountService} from '../account.service';
|
import {AccountService} from '../account.service';
|
||||||
import {GlobalVarsService} from '../global-vars.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 {BackendAPIService, User} from '../backend-api.service';
|
||||||
import {Observable, of} from 'rxjs';
|
import {Observable, of} from 'rxjs';
|
||||||
import {map} from 'rxjs/operators';
|
import {map} from 'rxjs/operators';
|
||||||
|
@ -51,7 +51,7 @@ export class ApproveComponent implements OnInit {
|
||||||
private identityService: IdentityService,
|
private identityService: IdentityService,
|
||||||
private accountService: AccountService,
|
private accountService: AccountService,
|
||||||
public globalVars: GlobalVarsService,
|
public globalVars: GlobalVarsService,
|
||||||
private signingService: SigningService,
|
// private signingService: SigningService,
|
||||||
private backendApi: BackendAPIService,
|
private backendApi: BackendAPIService,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
|
@ -77,9 +77,11 @@ export class ApproveComponent implements OnInit {
|
||||||
onSubmit(): void {
|
onSubmit(): void {
|
||||||
// TODO
|
// TODO
|
||||||
throw "replace all of this transaction parsing and checking with bitcoinjs-lib."
|
throw "replace all of this transaction parsing and checking with bitcoinjs-lib."
|
||||||
|
/*
|
||||||
const seedHex = ""
|
const seedHex = ""
|
||||||
const signedTransactionHex = this.signingService.signTransaction(seedHex, this.transactionHex);
|
const signedTransactionHex = this.signingService.signTransaction(seedHex, this.transactionHex);
|
||||||
this.finishFlow(signedTransactionHex);
|
this.finishFlow(signedTransactionHex);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
finishFlow(signedTransactionHex?: string): void {
|
finishFlow(signedTransactionHex?: string): void {
|
||||||
|
|
|
@ -7,30 +7,6 @@ import {GlobalVarsService} from './global-vars.service';
|
||||||
import {CookieService} from 'ngx-cookie';
|
import {CookieService} from 'ngx-cookie';
|
||||||
import {SigningService} from './signing.service';
|
import {SigningService} from './signing.service';
|
||||||
import {HttpParams} from '@angular/common/http';
|
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({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
|
@ -89,11 +65,14 @@ export class IdentityService {
|
||||||
// Incoming Messages
|
// Incoming Messages
|
||||||
|
|
||||||
private handleSign(data: any): void {
|
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
|
// This will tell us whether we need full signing access or just ApproveLarge
|
||||||
// level of access.
|
// 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
|
// In the case that approve() fails, it responds with a message indicating
|
||||||
// that approvalRequired = true, which the caller can then uses to trigger
|
// that approvalRequired = true, which the caller can then uses to trigger
|
||||||
|
@ -102,21 +81,18 @@ export class IdentityService {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we get to this point, no approval UI was required. This typically
|
// TODO - this.signingService.signPSBT instead
|
||||||
// happens if the caller has full signing access or signing access for
|
if it's a transaction
|
||||||
// non-spending txns such as like, post, update profile, etc. In the
|
const signedTransactionHex = this.signingService.signPSBT(transaction details);
|
||||||
// latter case we need a subsequent check to ensure that the txn is not
|
else // just an action
|
||||||
// sending money to any public keys other than the sender himself.
|
const signedActionHex = this.signingService.signActiov(action details);
|
||||||
if (!this.approveSpending(data)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const seedHex = this.cryptoService.decryptSeedHex(encryptedSeedHex, this.globalVars.hostname);
|
|
||||||
const signedTransactionHex = this.signingService.signTransaction(seedHex, transactionHex);
|
|
||||||
|
|
||||||
|
// TODO figure this out...
|
||||||
this.respond(id, {
|
this.respond(id, {
|
||||||
signedTransactionHex,
|
signedTransactionHex,
|
||||||
|
signedActionHex,
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleJwt(data: any): void {
|
private handleJwt(data: any): void {
|
||||||
|
@ -163,42 +139,12 @@ export class IdentityService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Access levels
|
// Access levels
|
||||||
|
|
||||||
private getRequiredAccessLevel(transactionHex: string): AccessLevel {
|
// TODO implement for lbry
|
||||||
const txBytes = new Buffer(transactionHex, 'hex');
|
// private getRequiredAccessLevel(transactionHex: string): AccessLevel {
|
||||||
const transaction = Transaction.fromBytes(txBytes)[0] as Transaction<any>;
|
// 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
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
private hasAccessLevel(data: any, requiredAccessLevel: AccessLevel): boolean {
|
private hasAccessLevel(data: any, requiredAccessLevel: AccessLevel): boolean {
|
||||||
const { payload: { encryptedSeedHex, accessLevel, accessLevelHmac }} = data;
|
const { payload: { encryptedSeedHex, accessLevel, accessLevelHmac }} = data;
|
||||||
|
@ -210,25 +156,6 @@ export class IdentityService {
|
||||||
return this.cryptoService.validAccessLevelHmac(accessLevel, seedHex, accessLevelHmac);
|
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<any>;
|
|
||||||
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 {
|
private approve(data: any, accessLevel: AccessLevel): boolean {
|
||||||
const hasAccess = this.hasAccessLevel(data, accessLevel);
|
const hasAccess = this.hasAccessLevel(data, accessLevel);
|
||||||
const hasEncryptionKey = this.cryptoService.hasSeedHexEncryptionKey(this.globalVars.hostname);
|
const hasEncryptionKey = this.cryptoService.hasSeedHexEncryptionKey(this.globalVars.hostname);
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import KeyEncoder from 'key-encoder';
|
import KeyEncoder from 'key-encoder';
|
||||||
import * as jsonwebtoken from 'jsonwebtoken';
|
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 * 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.
|
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 {
|
export class SigningService {
|
||||||
|
|
||||||
constructor(
|
constructor() { }
|
||||||
private cryptoService: CryptoService,
|
|
||||||
) { }
|
|
||||||
|
|
||||||
// this should be audited and go into a library. hobbled this together from
|
// this should be audited and go into a library. hobbled this together from
|
||||||
// code in bitcoinjs-lib.
|
// code in bitcoinjs-lib.
|
||||||
|
@ -75,39 +70,29 @@ export class SigningService {
|
||||||
}
|
}
|
||||||
|
|
||||||
signJWT(seedHex: string): string {
|
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 keyEncoder = new KeyEncoder('secp256k1');
|
||||||
const encodedPrivateKey = keyEncoder.encodePrivate(seedHex, 'raw', 'pem');
|
const encodedPrivateKey = keyEncoder.encodePrivate(seedHex, 'raw', 'pem');
|
||||||
return jsonwebtoken.sign({ }, encodedPrivateKey, { algorithm: 'ES256', expiresIn: 60 * 10 });
|
return jsonwebtoken.sign({ }, encodedPrivateKey, { algorithm: 'ES256', expiresIn: 60 * 10 });
|
||||||
}
|
}
|
||||||
|
|
||||||
signAction(seedHex: string, actionHex: string): string {
|
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.
|
// 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 privateKey = this.cryptoService.seedHexToPrivateKey(seedHex);
|
||||||
|
|
||||||
const actionBytes = new Buffer(actionHex, 'hex');
|
const actionBytes = new Buffer(actionHex, 'hex');
|
||||||
const actionHash = new Buffer(sha256.x2(actionBytes), 'hex');
|
const actionHash = new Buffer(sha256.x2(actionBytes), 'hex');
|
||||||
const signature = privateKey.sign(actionHash);
|
const signature = privateKey.sign(actionHash);
|
||||||
return new Buffer(signature.toDER()).toString('hex');
|
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');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue