namespace Riddle { public sealed class Solution { public uint8[] data { get; private set; } private uint8[] secret { get; private set; } internal uint8[] reply_key { get; set; } public Solution(uint8[] secret, uint8[] data) { this.data = data; this.secret = secret; } public uint8[] encrypt_connection_details(InetSocketAddress address) { print(@"Addy: $(address.address.to_string())\n"); var serialised = serialise_address(address); return Sodium.Asymmetric.Sealing.seal(serialised, reply_key); } public static uint8[]? verify_solved_response(Message response, uint8[] author_signing_key) { return Sodium.Asymmetric.Signing.verify(Base64.decode(response.items[0]), author_signing_key); } public static InetSocketAddress? decrypt_connection_details(uint8[] verified_response, uint8[] reply_public_key, uint8[] reply_secret_key) { var data = Sodium.Asymmetric.Sealing.unseal(verified_response, reply_public_key, reply_secret_key); if(data == null) { return null; } var parts = ((string)data).split(" ", 2); return new InetSocketAddress.from_string(parts[0], uint.parse(parts[1])); } private uint8[] serialise_address(InetSocketAddress address) { var s = @"$(address.address) $(address.port)"; return s.data; } public SolutionEnvelope seal(string riddle_id, uint8[] riddle_encryption_key) { var encrypted_data = Sodium.Asymmetric.Sealing.seal(data, riddle_encryption_key); var encrypted_reply_key = Sodium.Asymmetric.Sealing.seal(reply_key, riddle_encryption_key); return new SolutionEnvelope() { identifier = riddle_id, signed_data = Sodium.Asymmetric.Signing.sign(encrypted_data, secret), signed_reply_key = Sodium.Asymmetric.Signing.sign(encrypted_reply_key, secret) }; } } }