Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions src/application/clients/crux-wallet-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
IAddress,
IAddressMapping,
IAssetMatcher,
ICruxDecryptedPrivateInformation,
ICruxUserRegistrationStatus,
SubdomainRegistrationStatus,
SubdomainRegistrationStatusDetail,
Expand Down Expand Up @@ -233,7 +234,7 @@ export class CruxWalletClient {
}

@throwCruxClientError
public blacklistUsers = async (fullCruxIDs: string[]): Promise<{success: string[], failures: string[]}> => {
public putBlacklistedUsers = async (fullCruxIDs: string[]): Promise<{success: string[], failures: string[]}> => {
await this.initPromise;
const cruxUserWithKey = await this.getCruxUserByKey();
if (!cruxUserWithKey) {
Expand All @@ -249,11 +250,24 @@ export class CruxWalletClient {
registeredCruxUsers.push(fullCruxID);
}
}
cruxUserWithKey.setBlacklistedCruxIDs(registeredCruxUsers);
const decryptedPrivateInfo: ICruxDecryptedPrivateInformation = (await this.keyManager!.symmetricDecrypt!(cruxUserWithKey.privateInformation)) as ICruxDecryptedPrivateInformation;
decryptedPrivateInfo.blacklistedCruxUsers = registeredCruxUsers;
cruxUserWithKey.setPrivateInformation(decryptedPrivateInfo, this.keyManager!);
await this.cruxUserRepository.save(cruxUserWithKey, this.getKeyManager());
return {success: registeredCruxUsers, failures};
}

@throwCruxClientError
public getBlacklistedUsers = async (): Promise<string[]> => {
await this.initPromise;
const cruxUserWithKey = await this.getCruxUserByKey();
if (!cruxUserWithKey) {
throw ErrorHelper.getPackageError(null, PackageErrorCode.UserDoesNotExist);
}
const decryptedPrivateInfo: ICruxDecryptedPrivateInformation = (await this.keyManager!.symmetricDecrypt!(cruxUserWithKey.privateInformation)) as ICruxDecryptedPrivateInformation;
return decryptedPrivateInfo.blacklistedCruxUsers;
}

// @throwCruxClientError
public putPrivateAddressMap = async (fullCruxIDs: string[], newAddressMap: IAddressMapping): Promise<IPutPrivateAddressMapResult> => {
await this.initPromise;
Expand Down
20 changes: 17 additions & 3 deletions src/core/entities/crux-user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,15 @@ export interface ICruxUserInformation {
export interface ICruxUserData {
configuration: ICruxUserConfiguration;
privateAddresses: ICruxUserPrivateAddresses;
privateInformation: string;
}

export interface ICruxUserConfiguration {
enabledAssetGroups: string[];
// blacklistedCruxUsers: string[];
}

export interface ICruxDecryptedPrivateInformation {
blacklistedCruxUsers: string[];
}

Expand Down Expand Up @@ -63,6 +68,7 @@ export class CruxUser {
private cruxUserConfig!: ICruxUserConfiguration;
private cruxUserPrivateAddresses!: ICruxUserPrivateAddresses;
private cruxDomain!: CruxDomain;
private cruxPrivateInformation!: string;

constructor(cruxUserSubdomain: string, cruxDomain: CruxDomain, addressMap: IAddressMapping, cruxUserInformation: ICruxUserInformation, cruxUserData: ICruxUserData, publicKey?: string) {
this.setCruxDomain(cruxDomain);
Expand All @@ -72,6 +78,7 @@ export class CruxUser {
this.setCruxUserConfig(cruxUserData.configuration);
this.setPublicKey(publicKey);
this.setCruxUserPrivateAddresses(cruxUserData.privateAddresses);
this.setCruxUserPrivateInformation(cruxUserData.privateInformation);
log.debug("CruxUser initialised");
}
get cruxID() {
Expand All @@ -92,6 +99,9 @@ export class CruxUser {
get privateAddresses() {
return this.cruxUserPrivateAddresses;
}
get privateInformation() {
return this.cruxPrivateInformation;
}
public setSupportedAssetGroups = () => {
this.cruxUserConfig.enabledAssetGroups = this.cruxDomain.config.supportedAssetGroups;
}
Expand All @@ -112,8 +122,9 @@ export class CruxUser {
throw new BaseError(null, "Not supported by the keyManager in use");
}
}
public setBlacklistedCruxIDs = (blacklistedCruxIDs: string[]) => {
this.cruxUserConfig.blacklistedCruxUsers = blacklistedCruxIDs;
public setPrivateInformation = async (decryptedPrivateInfo: ICruxDecryptedPrivateInformation, keyManager: IKeyManager) => {
const encryptedPrivateInfo: string = await keyManager.symmetricEncrypt!(decryptedPrivateInfo);
this.cruxPrivateInformation = encryptedPrivateInfo;
}
public getAddressFromAsset = async (asset: IGlobalAsset, keyManager?: IKeyManager): Promise<IAddress|undefined> => {
let address: IAddress|undefined;
Expand Down Expand Up @@ -178,7 +189,7 @@ export class CruxUser {
private setCruxUserConfig = (cruxUserConfiguration: ICruxUserConfiguration) => {
// TODO: validation of the configurations
this.cruxUserConfig = {
blacklistedCruxUsers: cruxUserConfiguration.blacklistedCruxUsers,
// blacklistedCruxUsers: cruxUserConfiguration.blacklistedCruxUsers,
enabledAssetGroups: cruxUserConfiguration.enabledAssetGroups || [],
};
}
Expand All @@ -194,6 +205,9 @@ export class CruxUser {
this.cruxUserPrivateAddresses = cruxUserPrivateAddresses;
}
}
private setCruxUserPrivateInformation = async (privateInfo: string) => {
this.cruxPrivateInformation = privateInfo;
}
}

export interface IAssetMatcher {
Expand Down
2 changes: 2 additions & 0 deletions src/core/interfaces/key-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ export interface IKeyManager {
getPubKey: () => Promise<string>;
deriveSharedSecret?: (publicKey: string) => Promise<string>;
decryptMessage?: (encryptedMessage: string) => Promise<string>;
symmetricEncrypt?: (content: object) => Promise<string>;
symmetricDecrypt?: (encryptedContent: string) => Promise<object>;
}

export const isInstanceOfKeyManager = (object: any) => {
Expand Down
9 changes: 9 additions & 0 deletions src/infrastructure/implementations/basic-key-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@ export class BasicKeyManager implements IKeyManager {
const decrypted = await ECIESEncryption.decrypt(toDecrypt, privateKey);
return decrypted.toString();
}
public symmetricEncrypt = async (content: object): Promise<string> => {
const encrypted = await Encryption.encryptJSON(content, await this.getDecryptedPrivateKey());
return JSON.stringify(encrypted);
}
public symmetricDecrypt = async (encryptedContent: string): Promise<object> => {
const encryptedContentObj = JSON.parse(encryptedContent);
const decrypted = await Encryption.decryptJSON(encryptedContentObj.encBuffer, encryptedContentObj.iv, await this.getDecryptedPrivateKey());
return decrypted;
}
private init = async (privateKey: string, getEncryptionKey?: () => Promise<string>): Promise<void> => {
let encryptionConstant: string;
if (getEncryptionKey) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { publicKeyToAddress } from "blockstack";
import { Encryption } from "src/packages/encryption";
import {CruxDomain} from "../../core/entities/crux-domain";
import { CruxSpec } from "../../core/entities/crux-spec";
import { CruxUser, IAddressMapping, ICruxUserConfiguration, ICruxUserData, ICruxUserInformation, ICruxUserPrivateAddresses, SubdomainRegistrationStatus } from "../../core/entities/crux-user";
import { CruxUser, IAddressMapping, ICruxDecryptedPrivateInformation, ICruxUserConfiguration, ICruxUserData, ICruxUserInformation, ICruxUserPrivateAddresses, SubdomainRegistrationStatus } from "../../core/entities/crux-user";
import { ICruxBlockstackInfrastructure } from "../../core/interfaces";
import {ICruxUserRepository, ICruxUserRepositoryOptions} from "../../core/interfaces/crux-user-repository";
import { IKeyManager } from "../../core/interfaces/key-manager";
Expand Down Expand Up @@ -57,12 +58,15 @@ export class BlockstackCruxUserRepository implements ICruxUserRepository {
}
public create = async (cruxIdSubdomain: string, keyManager: IKeyManager): Promise<CruxUser> => {
// Publishing an empty addressMap while registering the name to be fail safe
const privateInfo = {
blacklistedCruxUsers: [],
};
const cruxUserData: ICruxUserData = {
configuration: {
blacklistedCruxUsers: [],
enabledAssetGroups: [],
},
privateAddresses: {},
privateInformation: await keyManager.symmetricEncrypt!(privateInfo),
};
await this.putCruxpayObject(this.getCruxDomain().id, {}, keyManager);
const cruxUserInformation = await this.blockstackService.registerCruxId(this.getCruxIdFromSubdomain(cruxIdSubdomain), this.infrastructure.gaiaHub, keyManager);
Expand All @@ -79,10 +83,10 @@ export class BlockstackCruxUserRepository implements ICruxUserRepository {
let addressMap = {};
let cruxUserData: ICruxUserData = {
configuration: {
blacklistedCruxUsers: [],
enabledAssetGroups: [],
},
privateAddresses: {},
privateInformation: "",
};
let cruxpayPubKey;
if (cruxUserInformation.registrationStatus.status === SubdomainRegistrationStatus.DONE) {
Expand All @@ -107,12 +111,15 @@ export class BlockstackCruxUserRepository implements ICruxUserRepository {
return;
}
let addressMap = {};
const privateInfo = {
blacklistedCruxUsers: [],
};
let cruxUserData: ICruxUserData = {
configuration: {
blacklistedCruxUsers: [],
enabledAssetGroups: [],
},
privateAddresses: {},
privateInformation: await keyManager.symmetricEncrypt!(privateInfo),
};
let cruxpayPubKey = await keyManager.getPubKey();
if ([SubdomainRegistrationStatus.DONE, SubdomainRegistrationStatus.PENDING].includes(cruxUserInformation.registrationStatus.status)) {
Expand All @@ -122,13 +129,13 @@ export class BlockstackCruxUserRepository implements ICruxUserRepository {
const dereferencedCruxpayObject = this.dereferenceCruxpayObject(cruxpayObject);
addressMap = dereferencedCruxpayObject.addressMap;
if (dereferencedCruxpayObject.cruxUserData) {
cruxUserData = dereferencedCruxpayObject.cruxUserData;
cruxUserData = Object.assign(cruxUserData, dereferencedCruxpayObject.cruxUserData);
}
}
return new CruxUser(cruxID.components.subdomain, this.getCruxDomain(), addressMap, cruxUserInformation, cruxUserData, cruxpayPubKey);
}
public save = async (cruxUser: CruxUser, keyManager: IKeyManager): Promise<CruxUser> => {
const cruxpayObject = this.constructCruxpayObject(cruxUser.getAddressMap(), cruxUser.info, cruxUser.config, cruxUser.privateAddresses);
const cruxpayObject = this.constructCruxpayObject(cruxUser.getAddressMap(), cruxUser.info, cruxUser.config, cruxUser.privateAddresses, cruxUser.privateInformation);
await this.putCruxpayObject(cruxUser.domain.id, cruxpayObject, keyManager);
return cruxUser;
}
Expand Down Expand Up @@ -217,11 +224,12 @@ export class BlockstackCruxUserRepository implements ICruxUserRepository {
const finalURL = await new GaiaService(gaiaHub, this.cacheStorage).uploadContentToGaiaHub(filename, content, keyManager);
return finalURL;
}
private constructCruxpayObject = (addressMap: IAddressMapping, userInformation: ICruxUserInformation, userConfiguration: ICruxUserConfiguration, privateAddresses: ICruxUserPrivateAddresses): ICruxpayObject => {
private constructCruxpayObject = (addressMap: IAddressMapping, userInformation: ICruxUserInformation, userConfiguration: ICruxUserConfiguration, privateAddresses: ICruxUserPrivateAddresses, privateInformation: string): ICruxpayObject => {
const cruxpayObject: ICruxpayObject = cloneValue(addressMap);
cruxpayObject.__userData__ = {
configuration: userConfiguration,
privateAddresses,
privateInformation,
};
return cruxpayObject;
}
Expand Down