You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			170 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			TypeScript
		
	
			
		
		
	
	
			170 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			TypeScript
		
	
| import { sign } from 'curve25519-js';
 | |
| import { SessionKeyPair } from '../../../../receiver/keypairs';
 | |
| import { callUtilsWorker } from '../../../../webworker/workers/browser/util_worker_interface';
 | |
| import { getSodiumRenderer } from '../../../crypto';
 | |
| import { UserUtils } from '../../../utils';
 | |
| import { fromBase64ToArray, fromHexToArray } from '../../../utils/String';
 | |
| import { SogsBlinding } from '../sogsv3/sogsBlinding';
 | |
| 
 | |
| export class OpenGroupMessageV2 {
 | |
|   public serverId?: number;
 | |
|   public sender?: string;
 | |
|   public sentTimestamp: number;
 | |
|   public base64EncodedData: string;
 | |
|   public base64EncodedSignature?: string;
 | |
|   public filesToLink?: Array<number>;
 | |
| 
 | |
|   constructor(messageData: {
 | |
|     serverId?: number;
 | |
|     sender?: string;
 | |
|     sentTimestamp: number;
 | |
|     base64EncodedData: string;
 | |
|     base64EncodedSignature?: string;
 | |
|     filesToLink?: Array<number>;
 | |
|   }) {
 | |
|     const {
 | |
|       base64EncodedData,
 | |
|       sentTimestamp,
 | |
|       base64EncodedSignature,
 | |
|       sender,
 | |
|       serverId,
 | |
|       filesToLink,
 | |
|     } = messageData;
 | |
| 
 | |
|     this.base64EncodedData = base64EncodedData;
 | |
|     this.sentTimestamp = sentTimestamp;
 | |
|     this.base64EncodedSignature = base64EncodedSignature;
 | |
|     this.sender = sender;
 | |
|     this.serverId = serverId;
 | |
|     this.filesToLink = filesToLink;
 | |
|   }
 | |
| 
 | |
|   public static fromJson(json: Record<string, any>) {
 | |
|     const {
 | |
|       data: base64EncodedData,
 | |
|       timestamp: sentTimestamp,
 | |
|       server_id: serverId,
 | |
|       public_key: sender,
 | |
|       signature: base64EncodedSignature,
 | |
|       files: filesToLink,
 | |
|     } = json;
 | |
| 
 | |
|     if (!base64EncodedData || !sentTimestamp) {
 | |
|       window?.log?.info('invalid json to build OpenGroupMessageV2');
 | |
|       throw new Error('OpengroupV2Message fromJson() failed');
 | |
|     }
 | |
|     return new OpenGroupMessageV2({
 | |
|       base64EncodedData,
 | |
|       base64EncodedSignature,
 | |
|       sentTimestamp,
 | |
|       serverId,
 | |
|       sender,
 | |
|       filesToLink,
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   public async sign(ourKeyPair: SessionKeyPair | undefined): Promise<OpenGroupMessageV2> {
 | |
|     if (!ourKeyPair) {
 | |
|       window?.log?.warn("Couldn't find user X25519 key pair.");
 | |
|       throw new Error("Couldn't sign message");
 | |
|     }
 | |
| 
 | |
|     const data = fromBase64ToArray(this.base64EncodedData);
 | |
|     const signature = sign(new Uint8Array(ourKeyPair.privKey), data, null);
 | |
|     if (!signature || signature.length === 0) {
 | |
|       throw new Error("Couldn't sign message");
 | |
|     }
 | |
|     const base64Sig = await callUtilsWorker('arrayBufferToStringBase64', signature);
 | |
|     return new OpenGroupMessageV2({
 | |
|       base64EncodedData: this.base64EncodedData,
 | |
|       sentTimestamp: this.sentTimestamp,
 | |
|       base64EncodedSignature: base64Sig,
 | |
|       sender: this.sender,
 | |
|       serverId: this.serverId,
 | |
|       filesToLink: this.filesToLink,
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   public async signWithBlinding(serverPubKey: string): Promise<OpenGroupMessageV2> {
 | |
|     const signingKeys = await UserUtils.getUserED25519KeyPairBytes();
 | |
| 
 | |
|     if (!signingKeys) {
 | |
|       throw new Error('signWithBlinding: getUserED25519KeyPairBytes returned nothing');
 | |
|     }
 | |
| 
 | |
|     const sodium = await getSodiumRenderer();
 | |
|     const blindedKeyPair = SogsBlinding.getBlindingValues(
 | |
|       fromHexToArray(serverPubKey),
 | |
|       signingKeys,
 | |
|       sodium
 | |
|     );
 | |
| 
 | |
|     if (!blindedKeyPair) {
 | |
|       throw new Error('signWithBlinding: getBlindedPubKey returned nothing');
 | |
|     }
 | |
|     const data = fromBase64ToArray(this.base64EncodedData);
 | |
| 
 | |
|     const signature = await SogsBlinding.getSogsSignature({
 | |
|       blinded: true,
 | |
|       ka: blindedKeyPair.secretKey,
 | |
|       kA: blindedKeyPair.publicKey,
 | |
|       toSign: data,
 | |
|       signingKeys,
 | |
|     });
 | |
|     if (!signature || signature.length === 0) {
 | |
|       throw new Error("Couldn't sign message");
 | |
|     }
 | |
|     const base64Sig = await callUtilsWorker('arrayBufferToStringBase64', signature);
 | |
| 
 | |
|     return new OpenGroupMessageV2({
 | |
|       base64EncodedData: this.base64EncodedData,
 | |
|       sentTimestamp: this.sentTimestamp,
 | |
|       base64EncodedSignature: base64Sig,
 | |
|       sender: this.sender, // might need to be blindedPubkey
 | |
|       serverId: this.serverId,
 | |
|       filesToLink: this.filesToLink,
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   public toJson() {
 | |
|     const json = {
 | |
|       data: this.base64EncodedData,
 | |
|       timestamp: this.sentTimestamp,
 | |
|     } as Record<string, any>;
 | |
|     if (this.serverId) {
 | |
|       json.server_id = this.serverId;
 | |
|     }
 | |
|     if (this.sender) {
 | |
|       json.public_key = this.sender;
 | |
|     }
 | |
|     if (this.base64EncodedSignature) {
 | |
|       json.signature = this.base64EncodedSignature;
 | |
|     }
 | |
| 
 | |
|     if (this.filesToLink) {
 | |
|       json.files = this.filesToLink;
 | |
|     }
 | |
|     return json;
 | |
|   }
 | |
| 
 | |
|   public toBlindedMessageRequestJson() {
 | |
|     const json = {
 | |
|       message: this.base64EncodedData,
 | |
|       timestamp: this.sentTimestamp,
 | |
|     } as Record<string, any>;
 | |
|     if (this.serverId) {
 | |
|       json.server_id = this.serverId;
 | |
|     }
 | |
|     if (this.sender) {
 | |
|       json.public_key = this.sender;
 | |
|     }
 | |
|     if (this.base64EncodedSignature) {
 | |
|       json.signature = this.base64EncodedSignature;
 | |
|     }
 | |
|     if (this.filesToLink) {
 | |
|       json.files = this.filesToLink;
 | |
|     }
 | |
|     return json;
 | |
|   }
 | |
| }
 |