60 lines
		
	
	
	
		
			1.5 KiB
			
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
		
		
			
		
	
	
			60 lines
		
	
	
	
		
			1.5 KiB
			
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| 
								 | 
							
								// Copyright 2022 Signal Messenger, LLC
							 | 
						||
| 
								 | 
							
								// SPDX-License-Identifier: AGPL-3.0-only
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import { promisify } from 'util';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import { SignalService as Proto } from '../protobuf';
							 | 
						||
| 
								 | 
							
								import { calculateAgreement, generateKeyPair } from '../Curve';
							 | 
						||
| 
								 | 
							
								import { encryptAttachment, deriveSecrets } from '../Crypto';
							 | 
						||
| 
								 | 
							
								import * as Bytes from '../Bytes';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const PROVISIONING_INFO = 'Art Service Provisioning Message';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								export type AuthorizeArtCreatorOptionsType = Readonly<{
							 | 
						||
| 
								 | 
							
								  token: string;
							 | 
						||
| 
								 | 
							
								  pubKeyBase64: string;
							 | 
						||
| 
								 | 
							
								}>;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								export async function authorizeArtCreator({
							 | 
						||
| 
								 | 
							
								  token,
							 | 
						||
| 
								 | 
							
								  pubKeyBase64: theirPubKeyBase64,
							 | 
						||
| 
								 | 
							
								}: AuthorizeArtCreatorOptionsType): Promise<void> {
							 | 
						||
| 
								 | 
							
								  const { server } = window.textsecure;
							 | 
						||
| 
								 | 
							
								  if (!server) {
							 | 
						||
| 
								 | 
							
								    throw new Error('Server not ready');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const auth = await server.getArtAuth();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const ourKeys = generateKeyPair();
							 | 
						||
| 
								 | 
							
								  const theirPubKey = Bytes.fromBase64(theirPubKeyBase64);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const secret = calculateAgreement(theirPubKey, ourKeys.privKey);
							 | 
						||
| 
								 | 
							
								  const [aesKey, macKey] = deriveSecrets(
							 | 
						||
| 
								 | 
							
								    secret,
							 | 
						||
| 
								 | 
							
								    new Uint8Array(64),
							 | 
						||
| 
								 | 
							
								    Bytes.fromString(PROVISIONING_INFO)
							 | 
						||
| 
								 | 
							
								  );
							 | 
						||
| 
								 | 
							
								  const keys = Bytes.concatenate([aesKey, macKey]);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const { ciphertext } = encryptAttachment(
							 | 
						||
| 
								 | 
							
								    Proto.ArtProvisioningMessage.encode({
							 | 
						||
| 
								 | 
							
								      ...auth,
							 | 
						||
| 
								 | 
							
								    }).finish(),
							 | 
						||
| 
								 | 
							
								    keys
							 | 
						||
| 
								 | 
							
								  );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const envelope = Proto.ArtProvisioningEnvelope.encode({
							 | 
						||
| 
								 | 
							
								    publicKey: ourKeys.pubKey,
							 | 
						||
| 
								 | 
							
								    ciphertext,
							 | 
						||
| 
								 | 
							
								  }).finish();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const socket = await server.getArtProvisioningSocket(token);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  try {
							 | 
						||
| 
								 | 
							
								    await promisify(socket.sendBytes).call(socket, Buffer.from(envelope));
							 | 
						||
| 
								 | 
							
								  } finally {
							 | 
						||
| 
								 | 
							
								    socket.close(1000, 'goodbye');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 |