@ngraveio/ur-sign
Version:
Provides BC-UR types for signature request and response from cold wallets to hot wallets.
294 lines (223 loc) • 12.7 kB
Markdown
# Signing Protocol
This is the implementation of the [Signing Protocol](https://github.com/ngraveio/Research/blob/main/papers/nbcr-2023-003-sign.md) that is coin agnostic and can be used for any coin.
This package adds support for the following ur types:
| Type | [[CBOR Tag]](https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml) | Owner | Description | Definition |
| --------------------- | ------------------------------------------------------------------------ | ------ | --------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `sign-request` | 41411 | Ngrave | Blockchain-agnostic signature request type where type of the coin is identified by `coin-identity` | [[NBCR-2023-003]](https://github.com/ngraveio/Research/blob/main/papers/nbcr-2023-003-sign.md) |
| `sign-response` | 41412 | Ngrave | Blockchain-agnostic signature response type | [[NBCR-2023-003]](https://github.com/ngraveio/Research/blob/main/papers/nbcr-2023-003-sign.md) |
## Why Use `sign-request` and `sign-response`
The `sign-request` and `sign-response` UR types provide a standardized, blockchain-agnostic way to handle signature requests and responses. By using these UR types, developers can create a uniform protocol for signing transactions across different blockchains, ensuring compatibility and ease of integration. This standardization helps in reducing the complexity of handling multiple blockchain-specific signing protocols and enhances security by providing a consistent method for transaction verification and signing.
## Installing
To install, run:
```bash
yarn add @ngraveio/ur-sign
```
```bash
npm install --save @ngraveio/ur-sign
```
```typescript
import { SignRequest, SignResponse } from "@ngraveio/ur-sign";
```
## CDDL
**Sign Request:**
```cddl
sign-request = {
?request-id: uuid, ; Identifier of the signing request
coin-id: #6.41401(coin-identity), ; Provides information on the elliptic curve and the blockchain/coin
?derivation-path: #6.40304(keypath), ; Key path for signing this request
sign-data: bytes, ; Transaction to be decoded by the offline signer
?origin: text, ; Origin of this sign request, e.g. wallet name
?tx-type: int .default 1 ; Specify type of transaction required for some blockchains
?address: string / bytes ; Specify sender address if not already specified in the sign-data and derivation-path
}
request-id = 1
coin-id = 2
derivation-path = 3
sign-data = 4
origin = 5
tx-type = 6
address=7
```
**Sign Response:**
```cddl
sign-response = {
?request-id: uuid, ; Identifier of the signing request
signature: bytes, ; Signature result
?origin: text, ; The device info providing this signature
}
; request-id must be present in case of response to a sign-request where
; the request-id is specified
request-id = 1
signature = 2
origin = 3
```
## Examples:
### Bitcoin
#### Sign Request
```typescript
import { SignRequest } from "@ngraveio/ur-sign";
import { UUID } from "@ngraveio/ur-uuid";
import { CoinIdentity } from "@ngraveio/ur-coin-identity";
import { Keypath } from "@ngraveio/ur-blockchain-commons";
const requestId = new UUID(Buffer.from('3b5414375e3a450b8fe1251cbc2b3fb5', 'hex'));
const coinId = new CoinIdentity(8, 0); // Bitcoin
const derivationPath = new Keypath({ path: "m/44'/0'/0'/0/0" });
const signData = Buffer.from('0100000001abcdef', 'hex');
const origin = "NGRAVE ZERO";
const txType = 1;
const address = '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa';
const signRequest = new SignRequest({ requestId, coinId, derivationPath, signData, origin, txType, address });
const ur = signRequest.toUr();
console.log(ur.toString());
```
#### Sign Response
```typescript
import { SignResponse } from "@ngraveio/ur-sign";
import { UUID } from "@ngraveio/ur-uuid";
const requestId = new UUID(Buffer.from('3b5414375e3a450b8fe1251cbc2b3fb5', 'hex'));
const signature = Buffer.from('70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f000000000000000000', 'hex');
const origin = "NGRAVE ZERO";
const signResponse = new SignResponse({ requestId, signature, origin });
const ur = signResponse.toUr();
console.log(ur.toString());
```
### Ethereum
#### Sign Request
```typescript
import { SignRequest } from "@ngraveio/ur-sign";
import { UUID } from "@ngraveio/ur-uuid";
import { CoinIdentity } from "@ngraveio/ur-coin-identity";
import { Keypath } from "@ngraveio/ur-blockchain-commons";
const requestId = new UUID(Buffer.from('9b1deb4d3b7d4bad9bdd2b0d7b3dcb6d', 'hex'));
const coinId = new CoinIdentity(8, 60); // Ethereum
const derivationPath = new Keypath({ path: "m/44'/60'/0'/0/0" });
const signData = Buffer.from('f86c808504a817c80082520894', 'hex');
const origin = "NGRAVE ZERO";
const txType = 1;
const address = '0x742d35Cc6634C0532925a3b844Bc454e4438f44e';
const signRequest = new SignRequest({ requestId, coinId, derivationPath, signData, origin, txType, address });
const ur = signRequest.toUr();
console.log(ur.toString());
```
#### Sign Response
```typescript
import { SignResponse } from "@ngraveio/ur-sign";
import { UUID } from "@ngraveio/ur-uuid";
const requestId = new UUID(Buffer.from('9b1deb4d3b7d4bad9bdd2b0d7b3dcb6d', 'hex'));
const signature = Buffer.from('d4f0a7bcd95bba1fbb1051885054730e3f47064288575aacc102fbbf6a9a14daa066991e360d3e3406c20c00a40973eff37c7d641e5b351ec4a99bfe86f335f713', 'hex');
const origin = "NGRAVE ZERO";
const signResponse = new SignResponse({ requestId, signature, origin });
const ur = signResponse.toUr();
console.log(ur.toString());
```
### Solana
#### Sign Request
```typescript
import { SignRequest } from "@ngraveio/ur-sign";
import { UUID } from "@ngraveio/ur-uuid";
import { CoinIdentity } from "@ngraveio/ur-coin-identity";
import { Keypath } from "@ngraveio/ur-blockchain-commons";
const requestId = new UUID(Buffer.from('9b1deb4d3b7d4bad9bdd2b0d7b3dcb6d', 'hex'));
const coinId = new CoinIdentity(6, 501); // Solana
const derivationPath = new Keypath({ path: "m/44'/501'/0'/0'", sourceFingerprint: 934670036 });
const signData = Buffer.from('01000103c8d842a2f17fd7aab608ce2ea535a6e958dffa20caf669b347b911c4171965530f957620b228bae2b94c82ddd4c093983a67365555b737ec7ddc1117e61c72e0000000000000000000000000000000000000000000000000000000000000000010295cc2f1f39f3604718496ea00676d6a72ec66ad09d926e3ece34f565f18d201020200010c0200000000e1f50500000000', 'hex');
const origin = "NGRAVE LIQUID";
const txType = 1;
const address = '9FPebKDGZAdcpT7SpfB1UowuqobV8Zww9TwPDSyzXJMr';
const signRequest = new SignRequest({ requestId, coinId, derivationPath, signData, origin, txType, address });
const ur = signRequest.toUr();
console.log(ur.toString());
```
#### Sign Response
```typescript
import { SignResponse } from "@ngraveio/ur-sign";
import { UUID } from "@ngraveio/ur-uuid";
const requestId = new UUID(Buffer.from('9b1deb4d3b7d4bad9bdd2b0d7b3dcb6d', 'hex'));
const signature = Buffer.from('d4f0a7bcd95bba1fbb1051885054730e3f47064288575aacc102fbbf6a9a14daa066991e360d3e3406c20c00a40973eff37c7d641e5b351ec4a99bfe86f335f7', 'hex');
const origin = "NGRAVE ZERO";
const signResponse = new SignResponse({ requestId, signature, origin });
const ur = signResponse.toUr();
console.log(ur.toString());
```
### Tezos
#### Sign Request
```typescript
import { SignRequest } from "@ngraveio/ur-sign";
import { UUID } from "@ngraveio/ur-uuid";
import { CoinIdentity } from "@ngraveio/ur-coin-identity";
import { Keypath } from "@ngraveio/ur-blockchain-commons";
const requestId = new UUID(Buffer.from('9b1deb4d3b7d4bad9bdd2b0d7b3dcb6d', 'hex'));
const coinId = new CoinIdentity(6, 1729); // Tezos
const derivationPath = new Keypath({ path: "m/44'/1729'/0'/0'/0'", sourceFingerprint: 934670036 });
const signData = Buffer.from('f849808609184e72a00082271094000000000000000000000000000000000000000080a47f7465737432000000000000000000000000000000000000000000000000000000600057808080', 'hex');
const origin = "NGRAVE LIQUID";
const address = 'tz1gLTu4Yxj8tPAcriQVUdxv6BY9QyvzU1az';
const signRequest = new SignRequest({ requestId, coinId, derivationPath, signData, origin, address });
const ur = signRequest.toUr();
console.log(ur.toString());
```
#### Sign Response
```typescript
import { SignResponse } from "@ngraveio/ur-sign";
import { UUID } from "@ngraveio/ur-uuid";
const requestId = new UUID(Buffer.from('9b1deb4d3b7d4bad9bdd2b0d7b3dcb6d', 'hex'));
const signature = Buffer.from('9fb423ee0b1ad3d3ad359c22d1e79048789c232813663fd5d8a1223458082ea844f5e87bf77db3b997aa4c847e23047c042003e3b204cea9ae0e1bf6fdcaaf09', 'hex');
const origin = "NGRAVE ZERO";
const signResponse = new SignResponse({ requestId, signature, origin });
const ur = signResponse.toUr();
console.log(ur.toString());
```
### MultiversX
#### Sign Request
```typescript
import { SignRequest } from "@ngraveio/ur-sign";
import { UUID } from "@ngraveio/ur-uuid";
import { CoinIdentity } from "@ngraveio/ur-coin-identity";
import { Keypath } from "@ngraveio/ur-blockchain-commons";
const requestId = new UUID(Buffer.from('9b1deb4d3b7d4bad9bdd2b0d7b3dcb6d', 'hex'));
const coinId = new CoinIdentity(6, 508); // MultiversX
const derivationPath = new Keypath({ path: "m/44'/508'/0'/0'/1'", sourceFingerprint: 934670036 });
const signData = Buffer.from('f849808609184e72a00082271094000000000000000000000000000000000000000080a47f7465737432000000000000000000000000000000000000000000000000000000600057808080', 'hex');
const origin = "NGRAVE LIQUID";
const signRequest = new SignRequest({ requestId, coinId, derivationPath, signData, origin });
const ur = signRequest.toUr();
console.log(ur.toString());
```
#### Sign Response
```typescript
import { SignResponse } from "@ngraveio/ur-sign";
import { UUID } from "@ngraveio/ur-uuid";
const requestId = new UUID(Buffer.from('9b1deb4d3b7d4bad9bdd2b0d7b3dcb6d', 'hex'));
const signature = Buffer.from('9fb423ee0b1ad3d3ad359c22d1e79048789c232813663fd5d8a1223458082ea844f5e87bf77db3b997aa4c847e23047c042003e3b204cea9ae0e1bf6fdcaaf09', 'hex');
const origin = "NGRAVE ZERO";
const signResponse = new SignResponse({ requestId, signature, origin });
const ur = signResponse.toUr();
console.log(ur.toString());
```
### Stellar
#### Sign Request
```typescript
import { SignRequest } from "@ngraveio/ur-sign";
import { UUID } from "@ngraveio/ur-uuid";
import { CoinIdentity } from "@ngraveio/ur-coin-identity";
import { Keypath } from "@ngraveio/ur-blockchain-commons";
const requestId = new UUID(Buffer.from('9b1deb4d3b7d4bad9bdd2b0d7b3dcb6d', 'hex'));
const coinId = new CoinIdentity(6, 148); // Stellar
const derivationPath = new Keypath({ path: "m/44'/148'/0'/0'/2'", sourceFingerprint: 934670036 });
const signData = Buffer.from('00000002000000002df26f5fc2916d823126414b0cde52203a4f54222e1f3c82f2c82bf7c4e2d76d000000640011b3dc0000000100000001000000000000006400000000646e9655000000010000000c48656c6c6f20576f726c642100000001000000000000000100000000321911377e1664d677a85ab30acd1262522f989f0f31da613219e8396278cdb90000000000000002540be4000000000000000000', 'hex');
const origin = "NGRAVE LIQUID";
const signRequest = new SignRequest({ requestId, coinId, derivationPath, signData, origin });
const ur = signRequest.toUr();
console.log(ur.toString());
```
#### Sign Response
```typescript
import { SignResponse } from "@ngraveio/ur-sign";
import { UUID } from "@ngraveio/ur-uuid";
const requestId = new UUID(Buffer.from('9b1deb4d3b7d4bad9bdd2b0d7b3dcb6d', 'hex'));
const signature = Buffer.from('9fb423ee0b1ad3d3ad359c22d1e79048789c232813663fd5d8a1223458082ea844f5e87bf77db3b997aa4c847e23047c042003e3b204cea9ae0e1bf6fdcaaf09', 'hex');
const origin = "NGRAVE ZERO";
const signResponse = new SignResponse({ requestId, signature, origin });
const ur = signResponse.toUr();
console.log(ur.toString());
```