| 
						
					 | 
					 | 
					@@ -2239,53 +2239,60 @@ static void _tf_ssb_private_message_decrypt_work(tf_ssb_t* ssb, void* user_data)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (found)
 | 
					 | 
					 | 
					 | 
						if (found)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						{
 | 
					 | 
					 | 
					 | 
						{
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							uint8_t* decoded = tf_malloc(work->message_size);
 | 
					 | 
					 | 
					 | 
							if (work->message_size >= strlen(".box") && memcmp(work->message + work->message_size - strlen(".box"), ".box", strlen(".box")) == 0)
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							int decoded_length = tf_base64_decode(work->message, work->message_size - strlen(".box"), decoded, work->message_size);
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							uint8_t* nonce = decoded;
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							uint8_t* public_key = decoded + crypto_box_NONCEBYTES;
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							if (public_key + crypto_secretbox_KEYBYTES < decoded + decoded_length)
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							{
 | 
					 | 
					 | 
					 | 
							{
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								uint8_t shared_secret[crypto_secretbox_KEYBYTES] = { 0 };
 | 
					 | 
					 | 
					 | 
								uint8_t* decoded = tf_malloc(work->message_size);
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								if (crypto_scalarmult(shared_secret, private_key, public_key) == 0)
 | 
					 | 
					 | 
					 | 
								int decoded_length = tf_base64_decode(work->message, work->message_size - strlen(".box"), decoded, work->message_size);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								uint8_t* nonce = decoded;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								uint8_t* public_key = decoded + crypto_box_NONCEBYTES;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								if (public_key + crypto_secretbox_KEYBYTES < decoded + decoded_length)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								{
 | 
					 | 
					 | 
					 | 
								{
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									enum
 | 
					 | 
					 | 
					 | 
									uint8_t shared_secret[crypto_secretbox_KEYBYTES] = { 0 };
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									if (crypto_scalarmult(shared_secret, private_key, public_key) == 0)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									{
 | 
					 | 
					 | 
					 | 
									{
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										k_recipient_header_bytes = crypto_secretbox_MACBYTES + sizeof(uint8_t) + crypto_secretbox_KEYBYTES
 | 
					 | 
					 | 
					 | 
										enum
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									};
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									for (uint8_t* p = decoded + crypto_box_NONCEBYTES + crypto_secretbox_KEYBYTES; p <= decoded + decoded_length - k_recipient_header_bytes;
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										 p += k_recipient_header_bytes)
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									{
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										uint8_t out[k_recipient_header_bytes] = { 0 };
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										int opened = crypto_secretbox_open_easy(out, p, k_recipient_header_bytes, nonce, shared_secret);
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										if (opened != -1)
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										{
 | 
					 | 
					 | 
					 | 
										{
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											int recipients = (int)out[0];
 | 
					 | 
					 | 
					 | 
											k_recipient_header_bytes = crypto_secretbox_MACBYTES + sizeof(uint8_t) + crypto_secretbox_KEYBYTES
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											uint8_t* body = decoded + crypto_box_NONCEBYTES + crypto_secretbox_KEYBYTES + k_recipient_header_bytes * recipients;
 | 
					 | 
					 | 
					 | 
										};
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											size_t body_size = decoded + decoded_length - body;
 | 
					 | 
					 | 
					 | 
										for (uint8_t* p = decoded + crypto_box_NONCEBYTES + crypto_secretbox_KEYBYTES; p <= decoded + decoded_length - k_recipient_header_bytes;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											uint8_t* decrypted = tf_malloc(body_size);
 | 
					 | 
					 | 
					 | 
											 p += k_recipient_header_bytes)
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											uint8_t* key = out + 1;
 | 
					 | 
					 | 
					 | 
										{
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											if (crypto_secretbox_open_easy(decrypted, body, body_size, nonce, key) != -1)
 | 
					 | 
					 | 
					 | 
											uint8_t out[k_recipient_header_bytes] = { 0 };
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
											int opened = crypto_secretbox_open_easy(out, p, k_recipient_header_bytes, nonce, shared_secret);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
											if (opened != -1)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											{
 | 
					 | 
					 | 
					 | 
											{
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
												work->decrypted = (const char*)decrypted;
 | 
					 | 
					 | 
					 | 
												int recipients = (int)out[0];
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
												work->decrypted_size = body_size - crypto_secretbox_MACBYTES;
 | 
					 | 
					 | 
					 | 
												uint8_t* body = decoded + crypto_box_NONCEBYTES + crypto_secretbox_KEYBYTES + k_recipient_header_bytes * recipients;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											}
 | 
					 | 
					 | 
					 | 
												size_t body_size = decoded + decoded_length - body;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											else
 | 
					 | 
					 | 
					 | 
												uint8_t* decrypted = tf_malloc(body_size);
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											{
 | 
					 | 
					 | 
					 | 
												uint8_t* key = out + 1;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
												work->error = "Received key to open secret box containing message body, but it did not work.";
 | 
					 | 
					 | 
					 | 
												if (crypto_secretbox_open_easy(decrypted, body, body_size, nonce, key) != -1)
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
												{
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
													work->decrypted = (const char*)decrypted;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
													work->decrypted_size = body_size - crypto_secretbox_MACBYTES;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
												}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
												else
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
												{
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
													work->error = "Received key to open secret box containing message body, but it did not work.";
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
												}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											}
 | 
					 | 
					 | 
					 | 
											}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										}
 | 
					 | 
					 | 
					 | 
										}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									}
 | 
					 | 
					 | 
					 | 
									}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									else
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									{
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
										work->error = "crypto_scalarmult failed.";
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								}
 | 
					 | 
					 | 
					 | 
								}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								else
 | 
					 | 
					 | 
					 | 
								else
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								{
 | 
					 | 
					 | 
					 | 
								{
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									work->error = "crypto_scalarmult failed.";
 | 
					 | 
					 | 
					 | 
									work->error = "Encrypted message was not long enough to contain its one-time public key.";
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								}
 | 
					 | 
					 | 
					 | 
								}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								tf_free(decoded);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							}
 | 
					 | 
					 | 
					 | 
							}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							else
 | 
					 | 
					 | 
					 | 
							else
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							{
 | 
					 | 
					 | 
					 | 
							{
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								work->error = "Encrypted message was not long enough to contains its one-time public key.";
 | 
					 | 
					 | 
					 | 
								work->error = "Message does not end in \".box\".";
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							}
 | 
					 | 
					 | 
					 | 
							}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							tf_free(decoded);
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						}
 | 
					 | 
					 | 
					 | 
						}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						else
 | 
					 | 
					 | 
					 | 
						else
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						{
 | 
					 | 
					 | 
					 | 
						{
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					 
 |