aLiceを使って携帯で簡単にNFTの所有証明

# はじめに
表題の通り、[aLice](https://github.com/0x070696E65/aLice)というモバイルアプリを使用してNFTの所有証明を行います。aLiceはSymbolアカウントの署名アプリなので、使用するブロックチェーンはSymbolです。

NFTの所有証明というより、アカウントの所有証明を行うので、メタデータやマルチシグなど詰まる所色々できます。ここでは分かりやすくNFTを例にします。

そもそもアカウントの所有証明とは？ですが、「秘密鍵を知っていること」とします。秘密鍵と公開鍵のペアにより電子署名を行い、検証をすることで所有の証明とします。

# 署名用データの作成
何に対して署名するのかについてですが、これは正直なんでもいいです。どんな文字列でもいいのですが、例えばタイムスタンプなどを混ぜれば署名データに有効期限を設けることもできます。ここではシンプルにテキストとタイムスタンプとします。

```js
const unsignedData = {
  "text": "これはtestです",
  "timestamp": 1696404344
}
```
jsonにしていますが項目が１つであれば、ただの文字列でも良いです。
続いてこれを16進数にします。aLiceでは署名データは全て16進数で受け付けます。

```js
const unsignedDataHex = Buffer.from(JSON.stringify(unsignedData), 'utf-8').toString('hex')
```

これをaLiceに渡します。

以下をURLとしてwebやアプリからアクセスします。
```
alice://sign?type=request_sign_utf8&data={unsignedDataHex}&callback={callbackURL}
```
:::note info
- callbackURLも16進数にしてください。
- callbackURLを渡さない場合はaLice内で署名済みデータをコピーさせることができます
:::

もしくはこのURLをQRコードに変換することでカメラアプリなどからaLiceを直接起動できます。

クエリなど、詳しくはドキュメントをご覧ください
https://github.com/0x070696E65/aLice

# 署名済データの検証

以下のような署名済みデータがaLiceより返ってくるので、正しい署名かどうか検証します。各種SymbolのSDKを使います。なお、このとき返ってくる`original_data`は署名前データなのでこの16進数をutf-8に戻してあげると、タイムスタンプが入ったデータになります。この後の検証後に有効期限を設けた何かとして活用もできます。
```
http://callback.com/?signature=D4FA1855AC3E778EC2D7C28A5A53419C259E110752B77E62961ADDF6E79CA8D24D21FF16B454245096768DF230E6776AE1D7F35B76CC626F52B0E50ECF771F0F&original_data=7b2274657874223a22e38193e3828ce381af74657374e381a7e38199222c2274696d657374616d70223a313639363430343334347d&pubkey=13B00FBB13C7644E13BD786F0EA4F97820022A2606759793A5D3525A03F92A2F&network=TestNet
```

### SDK v2の場合
```js
const signature = "D4FA1855AC3E778EC2D7C28A5A53419C259E110752B77E62961ADDF6E79CA8D24D21FF16B454245096768DF230E6776AE1D7F35B76CC626F52B0E50ECF771F0F";
const original_data = "7b2274657874223a22e38193e3828ce381af74657374e381a7e38199222c2274696d657374616d70223a313639363430343334347d";
const pubkey = "13B00FBB13C7644E13BD786F0EA4F97820022A2606759793A5D3525A03F92A2F";
const verify = KeyPair.verify(Convert.hexToUint8(pubkey), Convert.hexToUint8(original_data), Convert.hexToUint8(signature));
console.log(verify);
```

### SDK v3の場合
```js
const signature = "D4FA1855AC3E778EC2D7C28A5A53419C259E110752B77E62961ADDF6E79CA8D24D21FF16B454245096768DF230E6776AE1D7F35B76CC626F52B0E50ECF771F0F";
const original_data = "7b2274657874223a22e38193e3828ce381af74657374e381a7e38199222c2274696d657374616d70223a313639363430343334347d";
const pubkey = "13B00FBB13C7644E13BD786F0EA4F97820022A2606759793A5D3525A03F92A2F";
const verifier = new symbolSdk.default.symbol.Verifier(new symbolSdk.default.symbol.PublicKey(pubkey));
const verify = verifier.verify(
        symbolSdk.default.utils.hexToUint8(original_data), 
        new symbolSdk.default.symbol.Signature(signature));
console.log(verify);
```

### C# SDKの場合
```cs
var signature = "D4FA1855AC3E778EC2D7C28A5A53419C259E110752B77E62961ADDF6E79CA8D24D21FF16B454245096768DF230E6776AE1D7F35B76CC626F52B0E50ECF771F0F";
var original_data = "7b2274657874223a22e38193e3828ce381af74657374e381a7e38199222c2274696d657374616d70223a313639363430343334347d";
var pubkey = "13B00FBB13C7644E13BD786F0EA4F97820022A2606759793A5D3525A03F92A2F";
var verifier = new Verifier(new PublicKey(Converter.HexToBytes(pubkey)));
var verify = verifier.Verify(Converter.HexToBytes(original_data), new Signature(Converter.HexToBytes(signature)));
Console.WriteLine(verify);
```

いずれも`true`が返ってくればこの公開鍵によって署名されたデータであることが証明されます。
つまり、この公開鍵に対しての秘密鍵を知っているユーザーであることが分かりました。

あとは、この公開鍵を使って煮るなり焼くなりしてください。

あまり詳しくはありませんが、IoTデバイスと連携すれば所有するNFTによって部屋の鍵を開けるなども可能でしょう。NFTをチケットとしてイベントに参加も容易になります。

この公開鍵を持つアカウントにメタデータがあれば、その記載されている内容が証明書になるかもしれません。それが権威ある機関アカウントが登録したメタデータであれば、、、のように考えうるユースケースは無限にありそうです。

aLiceは署名するだけのモバイルアプリなのでウォレットとは呼び難いですが、ノードへのアナウンス機構を誰かが作成すれば店舗での支払いを行うこともできると思います。