123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- using Invercargill;
- namespace Riddle {
- public class DecentralisedNameInfo : NameInfo {
- public uint8[] public_key { get; protected set; }
- private uint8[] raw_data { get; protected set; }
- public override string get_encoded() {
- return Base64.encode(raw_data);
- }
- public DecentralisedNameInfo.from_string(string encoded_name_info) throws NameInfoError {
- raw_data = Base64.decode (encoded_name_info);
- public_key = raw_data[0:Sodium.Asymmetric.Signing.PUBLIC_KEY_BYTES];
- var signed_message = raw_data[Sodium.Asymmetric.Signing.PUBLIC_KEY_BYTES:];
- var data = Sodium.Asymmetric.Signing.verify (signed_message, public_key);
- if(data == null) {
- throw new NameInfoError.BAD_DATA("Invalid signature");
- }
- parse_base_info ((string)data);
- validate_base_info();
- if(!name.has_suffix (".rns")) {
- throw new NameInfoError.INVALID("Decentralised names must end in '.rns'.");
- }
- var expected_suffix = generate_suffix(get_root_name(name), public_key);
- if(!name.has_suffix (expected_suffix)) {
- throw new NameInfoError.INVALID("The name and private key combination is not valid.");
- }
- }
- public DecentralisedNameInfo(string name, string key, DateTime expiry, Enumerable<NameProperty> properties) {
- var keys = key.split(":");
- public_key = Base64.decode(keys[0]);
- var secret_key = Base64.decode(keys[1]);
- var name_parts = name.split(".");
- var root_name = name_parts[name_parts.length-1];
- this.name = name + generate_suffix(root_name, public_key);
- expires = expiry.to_utc();
- effective = new DateTime.now_utc();
- this.properties = properties.to_sequence();
- var data = stringify_base_info();
- var signed = Sodium.Asymmetric.Signing.sign (data.data, secret_key);
- // Data is public-key followed by signed data
- raw_data = new uint8[public_key.length + signed.length];
- for(var i = 0; i < raw_data.length; i++) {
- if(i < public_key.length) {
- raw_data[i] = public_key[i];
- }
- else {
- raw_data[i] = signed[i-public_key.length];
- }
- }
- }
- public static string generate_key() {
- var pk = new uint8[Sodium.Asymmetric.Signing.PUBLIC_KEY_BYTES];
- var sk = new uint8[Sodium.Asymmetric.Signing.SECRET_KEY_BYTES];
- Sodium.Asymmetric.Signing.generate_keypair (pk, sk);
-
- var pk_enc = Base64.encode (pk);
- var sk_enc = Base64.encode (sk);
- return @"$pk_enc:$sk_enc";
- }
- public static string generate_suffix(string root_name, uint8[] public_key) {
- var checksum = new Checksum(ChecksumType.SHA512);
- var name_data = root_name.data;
- checksum.update(name_data, name_data.length);
- checksum.update(public_key, public_key.length);
- var digest = new uint8[64];
- size_t size = digest.length;
- checksum.get_digest(digest, ref size);
- var suffix = @".$(encode_hash(digest)).rns";
- return suffix;
- }
- public static string get_root_name(string name) {
- var parts = name.split(".");
- return parts[parts.length - 3];
- }
- private const string ENCODING_CHARS = "abcdefghijklmnopqrstuvwxyz234567";
- private static string encode_hash(uint8[] data) {
- var s = new char[6];
- for(var i = 0; i < 6; i++) {
- var v = data[i*10];
- var ev = v / 8;
- s[i] = ENCODING_CHARS[ev];
- }
- return (string)s;
- }
- }
- }
|