- aLice -はSymbolアカウントで署名ができるMobileAppです。
ユーザーはSymbolアカウントの秘密鍵をユーザが設定するパスワードにて暗号化し端末に保存しています。
他のMobileAppやwebサイトから署名が必要なデータを送ることでユーザが署名し署名データを返すことができます。
- aLice - が出来ることは以下です
- aLice - のカスタムURLスキームは alice://
です。prefixにはsign
を使います。
クエリパラメータ | 値 |
---|---|
type | request_sign_transaction, request_sign_utf8, request_sign_binary_hex, request_pubkey, request_sign_batches |
data | 署名するデータ(string) |
callback | これらをhexにする(https://hogehoge.com/callback, sampleApp://callback/) |
batch | batch0, batch1, batch2 … |
method | post |
redirect_url | これらをhexにする (https://google.com) |
ex)
alice://sign?data={data}&type={request_type}&callback={callbackURL}
&method=post
を与えてやるとPOSTにて送信します。
その際は、aLiceの画面に留まるため
&redirect_url={redirect_url}
を追加してやると画面が遷移します。redirect_url
にパラメータを追加するとそのまま遷移するのでtoken
などの受け渡しに使えるかと思います。
※redirect_urlもutf8をhexにして渡してください
postの場合は以下のようなJSONをBodyに含め送信します
{
"pubkey": "PUBLIC_KEY",
"original_data": "ORIGINAL_DATA",
"signature": "SIGNATURE"
}
ここに設定したURLに遷移(もしくはPOST送信)します。
ただし、これらは16進数にエンコードしてください
const callback = `sample://callback/param1=test`;
const url = `alice://sign?data=${transferTransaction.serialize()}&type=request_sign_transaction&callback=${Convert.uint8ToHex(callback)}`;
Symbolのトランザクションペイロードに署名します。
const transaction = facade.transactionFactory.create({
type: 'transfer_transaction_v1',
signerPublicKey: aliceKeyPair.publicKey,
recipientAddress: 'BOB_PLAIN_ADDRESS',
mosaics: [
{
mosaicId: 0x72C0212E67A08BCEn,
amount: 1_000000n
}
],
message: [0,...(new TextEncoder('utf-8')).encode('Hello, Symbol!!')],
fee: 1_000000n,
deadline,
});
const payload = symbolSdk.utils.uint8ToHex(transaction.serialize());
alice://sign?type=request_sign_transaction&data={payload}&callback={callbackURL}
sdk v2系の場合はhexへのコンバートは不要です
// v2
const payload = transaction.serialize();
Note: トランザクションのSignerPublicKeyはユーザが設定しているメインアカウントの公開鍵が自動的に設定されます。
以下をCallbackURLに返します。
{callbackUrl}?signed_payload={signedPayload}&pubkey={publicKey}&original_data={data}
signedPayloadは以下のように扱います
// v2 v2系では一度再構築しなおす必要があります
const hash = Transaction.createTransactionHash(payload, [... Convert.hexToUint8(generationHash)])
const signed = TransactionMapping.createFromPayload(payload);
const signedTx = new SignedTransaction(payload, hash, signed.signer?.publicKey!, signed.type, signed.type)
// v3 v3系ではそのままpayloadとして扱えますがput送信する時には以下のように扱う
const jsonObject = {
payload: payload
};
const d = JSON.stringify(jsonObject);
Note: ここでのoriginal_dataは送信時のhex_payloadです。
暗号化メッセージはTransferTransactionのみで使えます。
パラメータにに&recipient_publicKey_for_encrypt_message={RecipientPublicKey}
を追加で渡してください。なお、暗号化することでトランザクションのサイズは大きくなり手数料が変わります。追加で&fee_multiplier=100
とすることで手数料乗数を設定できます。このパラメータがない場合は100に設定されます・
UTF8文字列に署名します
文字列はそのままではなく16進数文字列にしてから送信してください
const data = Buffer.from('hello,symbol!', 'utf-8').toString('hex').toUpperCase()
alice://sign?type=request_sign_utf8&data={data}&callback={callbackURL}
以下をCallbackURLに返します。
{callbackUrl}?signature={signature}&pubkey={publicKey}&original_data={data}
バイナリデータに署名します
// v3
const data = symbolSdk.default.utils.uint8ToHex(new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00]))
// v2
const data = Convert.uint8ToHex(new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00]))
alice://sign?type=request_sign_binary_hex&data={data}&callback={callbackURL}
以下をCallbackURLに返します。
{callbackUrl}?signature={signature}&pubkey={publicKey}&original_data={data}
複数のInnerTransactionに全て署名します。
今の所Metal用です。
以下のようにtxsの16進数文字列をbatchクエリに追加してください。
データ数が大きくなることが想定されます。&method=post
にしてください。URLが長すぎると画面遷移できません。
import {MetalService} from "metal-on-symbol";
const { txs, key, additive } = await metalService.createForgeTxs(
type,
sourcePubAccount,
targetPubAccount,
targetId,
payaload,
additive,
metadataPool
);
let url = `alice://sign?type=request_sign_batches&method=post&callback=${callbackURL}`;
for(let i = 0; i < txs.length; i++){
url += `&batch${i}=${tx.serialize()}`
}
以下のようなJSONをBodyに含め送信します
{
"pubkey": "PUBLIC_KEY",
"signed0": "SIGNED_PAYLOAD_0",
"signed1": "SIGNED_PAYLOAD_1",
"signed2": "SIGNED_PAYLOAD_2",
...
}
ユーザが - aLice - のメインに設定しているアカウントの公開鍵(string)を返します。
ユーザが署名を拒否すると以下を返します
{callback}?error=sign_rejected
v3系の場合
// 返ってきた公開鍵とトランザクションの公開鍵が一致するかどうか
const publicKey = new symbolSdk.default.PublicKey("PUBLIC_KEY");
const tx = symbolSdk.default.symbol.TransactionFactory.deserialize(symbolSdk.utils.hexToUint8(payload));
console.log(symbolSdk.default.utils.uint8ToHex(tx.signerPublicKey.bytes) == symbolSdk.utils.uint8ToHex(publicKey.bytes));
// トランザクションの検証
console.log(facade.verifyTransaction(tx, tx.signature));
v3系の場合
const publicKey = new symbolSdk.default.PublicKey("PUBLIC_KEY");
const verifier = new facade.constructor.Verifier(publicKey);
console.log(verifier.verify(original_data, signature));