# Signing Data

Signing arbitrary data enables you to verify the user's possession of an account. This guide will walk you through the signing process and verification.

**Obtain a chain provider**

As covered in [Provider Activation](https://docs.constellationnetwork.io/stargazer-wallet/guide/provider-activation), obtain a chain provider for the networks you want to interact with. In the following examples, we will use both Ethereum and Constellation providers.

```typescript
const dagProvider = window.stargazer.getProvider("constellation");
const ethProvider = window.stargazer.getProvider("ethereum");
```

### Constellation Message Signing[​](https://docs.constellationnetwork.io/stargazer/Guide/signingData#constellation-message-signing) <a href="#constellation-message-signing" id="constellation-message-signing"></a>

#### Build a signature request[​](https://docs.constellationnetwork.io/stargazer/Guide/signingData#build-a-signature-request) <a href="#build-a-signature-request" id="build-a-signature-request"></a>

Constellation signatures for messages are done through a [signature request object](https://docs.constellationnetwork.io/stargazer-wallet/constellation-rpc-api/dag_signmessage). The signature request object is sent for the user to accept. Uppon approval, a signature of the whole object is returned.

```typescript
// Build the signature request
const signatureRequest: SignatureRequest = {
  content: "Sign this message to confirm your address",
  metadata: {
    user: "3feb69d6-d3f0-4812-9c93-384bee08afe8",
  },
};
```

#### Encode the signature request[​](https://docs.constellationnetwork.io/stargazer/Guide/signingData#encode-the-signature-request) <a href="#encode-the-signature-request" id="encode-the-signature-request"></a>

Requests need to be a `Base64 < JSON` encoded string to sign. The wallet will then generate the signature from the same characters that compose this encoded request.

```typescript
// Encode the signature request - Base64 < JSON < Request
const signatureRequestEnconded = window.btoa(JSON.stringify(signatureRequest));
```

#### Send the signature request[​](https://docs.constellationnetwork.io/stargazer/Guide/signingData#send-the-signature-request) <a href="#send-the-signature-request" id="send-the-signature-request"></a>

Once built and encoded, you can send the encoded signature request using the [`dag_signMessage`](https://docs.constellationnetwork.io/stargazer-wallet/constellation-rpc-api/dag_signmessage) RPC method.

**Important**

When the signature request is sent, the wallet will verify compliance with the schema of the [signature request object](https://docs.constellationnetwork.io/stargazer-wallet/constellation-rpc-api/dag_signmessage). If it does not comply, the wallet will throw an error.

```typescript
// Send the request and wait for the signature
await dagProvider.request({
  method: "dag_signMessage",
  params: [
    "DAG88C9WDSKH451sisyEP3hAkgCKn5DN72fuwjfX",
    signatureRequestEnconded,
  ],
});
// "3045022100b35798008516373fcc6eef75fe8e322ce8fe0dccc4802b052f3ddc7c6b5dc2900220154cac1e4f3e7d9a64f4ed9d2a518221b273fe782f037a5842725054f1c62280"
```

The returned signature corresponds to the SHA512 hash of the encoded signature request and the private key of the user. `ECDSA.sign(privateKey, sha512(signatureRequestEnconded))`.

*Read more about* [*Constellation signature verification*](https://docs.constellationnetwork.io/stargazer-wallet/guide/signing-data)

#### Get the account public key[​](https://docs.constellationnetwork.io/stargazer/Guide/signingData#get-the-account-public-key) <a href="#get-the-account-public-key" id="get-the-account-public-key"></a>

After you generate a signature from your encoded request, you need to retrieve the public key from the signer's account for future verification. This is due to the fact that Constellation signatures are not recoverable (i.e. do not contain the `v` parameter like in Ethereum).

```typescript
// Send the request and wait for the signature
await dagProvider.request({
  method: "dag_getPublicKey",
  params: ["DAG88C9WDSKH451sisyEP3hAkgCKn5DN72fuwjfX"],
});
// "0482c4566a9c4cbb6f23b9a31c96876501c71f5c04b35f416e0b2243113cce8fb386a2db0b3881d1c908d33465748b948649165a6705904120238999eed6eed1f4"
```

### Ethereum Message Signing[​](https://docs.constellationnetwork.io/stargazer/Guide/signingData#ethereum-message-signing) <a href="#ethereum-message-signing" id="ethereum-message-signing"></a>

The Stargazer Ethereum RPC API implements both [EIP-191](https://eips.ethereum.org/EIPS/eip-191) ([`personal_sign`](https://docs.constellationnetwork.io/stargazer-wallet/ethereum-rpc-api/personal_sign)) and [EIP-712](https://eips.ethereum.org/EIPS/eip-712) ([`eth_signTypedData`](https://docs.constellationnetwork.io/stargazer-wallet/ethereum-rpc-api/eth_signtypeddata)) as arbitrary message signing methods.

#### personal\_sign method[​](https://docs.constellationnetwork.io/stargazer/Guide/signingData#personal_sign-method) <a href="#personal_sign-method" id="personal_sign-method"></a>

The RPC API provided reveals the [`personal_sign`](https://docs.constellationnetwork.io/stargazer-wallet/ethereum-rpc-api/personal_sign) RPC method for message signing. In this case, the message signed is an arbitrary hex string prefixed by the `"\x19Ethereum Signed Message:\n"` string and the length of the message in bytes from [EIP-191](https://eips.ethereum.org/EIPS/eip-191#specification).

```typescript
// Send the request and wait for the signature
await dagProvider.request({
  method: "personal_sign",
  params: [
    "0x5369676e2074686973206d65737361676520746f20636f6e6669726d20796f7572206164647265737320616e64207573657249642033666562363964362d643366302d343831322d396339332d333834626565303861666538",
    "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83",
  ],
});
// "0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17bfdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b"

// Can also be a valid UTF-8 string
await dagProvider.request({
  method: "personal_sign",
  params: [
    "Sign this message to confirm your address and userId 3feb69d6-d3f0-4812-9c93-384bee08afe8",
    "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83",
  ],
});
// "0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17bfdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b"
```

The returned signature corresponds to the keccak256 hash of the prefix + message string and the private key of the user. `ECDSA.sign(privateKey, keccak256("\x19Ethereum Signed Message:\n" + len(message) + message))`.

*Read more about* [*Ethereum signature verification*](#ethereum-message-signing)

#### eth\_signTypedData method[​](https://docs.constellationnetwork.io/stargazer/Guide/signingData#eth_signtypeddata-method) <a href="#eth_signtypeddata-method" id="eth_signtypeddata-method"></a>

The RPC API provided reveals the [`eth_signTypedData`](https://docs.constellationnetwork.io/stargazer-wallet/ethereum-rpc-api/eth_signtypeddata) RPC method for typed message signing. In this case, the message signed is the hash of the typed data according to [EIP-712](https://eips.ethereum.org/EIPS/eip-712#specification) prefixed by the `"\x19\x01"` string according to [EIP-191](https://eips.ethereum.org/EIPS/eip-191#specification).

```typescript
await provider.request({
  method: "eth_signTypedData",
  params: [
    "0x567d0382442c5178105fC03bd52b8Db6Afb4fE40",
    {
      types: {
        DeviceControl: [
          {
            name: "principal",
            type: "AuthorizedEntity",
          },
          {
            name: "emergency",
            type: "AuthorizedEntity",
          },
        ],
        AuthorizedEntity: [
          {
            name: "address",
            type: "address",
          },
          {
            name: "validUntil",
            type: "uint256",
          },
        ],
        EIP712Domain: [
          {
            name: "name",
            type: "string",
          },
          {
            name: "version",
            type: "string",
          },
          {
            name: "chainId",
            type: "uint256",
          },
          {
            name: "verifyingContract",
            type: "address",
          },
        ],
      },
      domain: {
        name: "Stargazer Demo",
        version: "1.0.0",
        chainId: "3",
        verifyingContract: "0xeb14c9bb6c2dec2ecb9b278c9fa1ec763b04d545",
      },
      primaryType: "DeviceControl",
      message: {
        principal: {
          address: "0xeb14c9bb6c2dec2ecb9b278c9fa1ec763b04d545",
          validUntil: "1657823568",
        },
        emergency: {
          address: "0xcac3da343670abb46bc6e8e6d375b66217519093",
          validUntil: "1752517998",
        },
      },
    },
  ],
});
// "0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17bfdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b"
```

The returned signature corresponds to the keccak256 hash of the domainSeparator + hashStruct(message) and the private key of the user. `ECDSA.sign(privateKey, keccak256("\x19\x01" + domainSeparator + hashStruct(message))`.

*Read more about* [*Ethereum signature verification*](https://docs.constellationnetwork.io/stargazer/Guide/signingData#ethereum-signature-verification)

### Constellation Signature Verification[​](https://docs.constellationnetwork.io/stargazer/Guide/signingData#constellation-signature-verification) <a href="#constellation-signature-verification" id="constellation-signature-verification"></a>

For signature verification, we will be using the [@stardust-collective/dag4](https://www.npmjs.com/package/@stardust-collective/dag4) package. The following snippet illustrates how you can verify an encoded request signature.

```typescript
import { dag4 } from "@stardust-collective/dag4";

const publicKey = "account-public-key";
const signatureRequestEnconded = "the-base64-encoded-signature-request";
const signatureHex = "some-hex-encoded-signature";

const valid: boolean = dag4.keyStore.verify(
  publicKey,
  signatureRequestEnconded,
  signatureHex
);

const publicKeyAddress = dag4.keyStore.getDagAddressFromPublicKey(publicKey);
```

### Ethereum Signature Verification[​](https://docs.constellationnetwork.io/stargazer/Guide/signingData#ethereum-signature-verification) <a href="#ethereum-signature-verification" id="ethereum-signature-verification"></a>

For signature verification, we will be using the [ethers](https://www.npmjs.com/package/ethers) package. The following snippets illustrate how you can verify different message signatures.

eth\_personalSign

```typescript
import * as ethers from "ethers";

const accountWhichSigned = "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83";
const messageSigned = "some-message-the-user-signed";
const signatureHex = "some-hex-encoded-signature";

const messageHash = ethers.utils.hashMessage(messageSigned);
const recoveredAddress = ethers.utils.recoverAddress(messageHash, signatureHex);

if (recoveredAddress !== accountWhichSigned) {
  throw new Error("Signature is not valid");
}
```

eth\_signTypedData

```typescript
import * as ethers from "ethers";

const accountWhichSigned = "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83";
const messageSigned = {
  // The EIP-712 domain signed
  domain: {
    name: "Stargazer Demo",
    version: "1.0.0",
    chainId: 3,
    verifyingContract: "0xabcdefABCDEF1234567890abcdefABCDEF123456",
  },
  // The EIP-712 types signed
  types: {
    DeviceControl: [
      { name: "principal", type: "AuthorizedEntity" },
      { name: "emergency", type: "AuthorizedEntity" },
    ],
    AuthorizedEntity: [
      { name: "address", type: "address" },
      { name: "validUntil", type: "uint256" },
    ],
  },
  // The EIP-712 message signed
  value: {
    principal: {
      address: "0xEb14c9bb6C2DEc2eCb9B278C9fa1EC763B04d545",
      validUntil: 1657823568,
    },
    emergency: {
      address: "0xcAc3DA343670aBB46BC6E8e6d375B66217519093",
      validUntil: 1752517998,
    },
  },
};
const signatureHex = "some-hex-encoded-signature";

const messageHash = ethers.utils._TypedDataEncoder.hash(
  messageSigned.domain,
  messageSigned.types,
  messageSigned.value
);
const recoveredAddress = ethers.utils.recoverAddress(messageHash, signatureHex);

if (recoveredAddress !== accountWhichSigned) {
  throw new Error("Signature is not valid");
}
```
