/// <summary> /// Converts public key to CAN ID format. /// </summary> /// <param name="PublicKey">Ed25519 public key.</param> /// <returns>CAN ID that corresponds to the the public.</returns> public static byte[] PublicKeyToId(byte[] PublicKey) { CanCryptoKey key = new CanCryptoKey() { Type = CanCryptoKey.Types.KeyType.Ed25519, Data = ProtocolHelper.ByteArrayToByteString(PublicKey) }; byte[] hash = Crypto.Sha256(key.ToByteArray()); byte[] res = new byte[2 + hash.Length]; res[0] = 0x12; // SHA256 hash prefix res[1] = (byte)hash.Length; Array.Copy(hash, 0, res, 2, hash.Length); return(res); }
/// <summary> /// Refreshes profile server's IPNS record in CAN. /// </summary> /// <param name="IpnsRecord">IPNS record to refresh.</param> /// <param name="PublicKey">Public key of the IPNS record owner.</param> /// <returns>Structure describing whether the function succeeded and response provided by CAN server.</returns> public async Task <CanRefreshIpnsResult> RefreshIpnsRecord(CanIpnsEntry IpnsRecord, byte[] PublicKey) { log.Trace("(PublicKey:'{0}')", PublicKey.ToHex()); string ipnsRecordEncoded = IpnsRecord.ToByteArray().ToBase64UrlPad(true); CanCryptoKey cryptoKey = new CanCryptoKey() { Type = CanCryptoKey.Types.KeyType.Ed25519, Data = ProtocolHelper.ByteArrayToByteString(PublicKey) }; string keyEncoded = Base58Encoding.Encoder.Encode(cryptoKey.ToByteArray()); log.Debug("Encoding public key: {0}", keyEncoded); NameValueCollection args = new NameValueCollection(); args.Add("arg", ipnsRecordEncoded); args.Add("key", keyEncoded); CanApiResult apiResult = await SendRequest("name/upload", args); CanRefreshIpnsResult res = CanRefreshIpnsResult.FromApiResult(apiResult); if (res.Success) { res.IsCanError = false; // Check that the ID, path and sequence number match what we expect. string canId = CanApi.PublicKeyToId(PublicKey).ToBase58(); if (res.Details.Peer == canId) { string path = Encoding.UTF8.GetString(IpnsRecord.Value.ToByteArray()); if (res.Details.NewPath == path) { if (res.Details.NewSeq == IpnsRecord.Sequence) { // All OK. } else { log.Warn("CAN sequence is {0}, received {1}.", IpnsRecord.Sequence, res.Details.NewSeq); res.Success = false; res.Message = "CAN path in response does not match expected value."; } } else { log.Warn("CAN path is '{0}', received '{1}'.", path, res.Details.NewPath); res.Success = false; res.Message = "CAN path in response does not match expected value."; } } else { log.Warn("CAN ID is '{0}', received '{1}'.", canId, res.Details.Peer); res.Success = false; res.Message = "CAN ID in response does not match expected value."; } } if (res.Success) { log.Trace("(-):*.Success={0}", res.Success); } else { log.Trace("(-):*.Success={0},*.IsCanError={1},*.Message='{2}'", res.Success, res.IsCanError, res.Message); } return(res); }