# Signature Verification

Verify Beam requests with SHA-256 signatures and a shared secret.

When enabling the **Signature header** option, a SHA-256 hash will be calculated using a pre-shared key that you define, and will be appended to the HTTP request header or TCP packet. You can then independently re-calculate the SHA-256 hash on your server application in order to verify the connection request.

## Air for Cellular

To use the **Signature header** option, you must also enable one or more of the **IMEI Header**, **IMSI Header**, **MSISDN Header**, or **SIM ID Header** options, as well as create or select a **Pre-shared key**.

When Beam receives data from your device, it will use the following information to generate a secure hash:

- Pre-shared key `{PSK}`
- Device IMEI `{IMEI}`
- Subscriber IMSI `{IMSI}`
- Subscriber MSISDN `{MSISDN}`
- SIM ID `{SIM-ID}`
- Timestamp `{TS}`

This information is used to generate one of the following unique strings, based on which headers have been enabled:

- **HTTP/HTTPS Endpoints**:

  ```
  {PSK}x-soracom-imei={IMEI}x-soracom-imsi={IMSI}x-soracom-msisdn={MSISDN}x-soracom-sim-id={SIM-ID}x-soracom-timestamp={TS}
  ```

> [!NOTE]
>
> When using an HTTP/HTTPS endpoint, the HTTP headers appended to the request may appear in a different order. Your server application should always concatenate these headers in the following order:
>
> - Pre-shared key
> - IMEI
> - IMSI
> - MSISDN
> - SIM ID
> - Timestamp

- **TCP/TCPS Endpoint**:

  ```
  {PSK}imei={IMEI} imsi={IMSI} msisdn={MSISDN} simId={SIM-ID} timestamp={TS}
  ```

> [!WARNING]
>
> When using a TCP/TCPS endpoint, the header values and signature will be separate by a semicolon `;`. You can simply use the string value _before_ the semi-colon in the unique string.

Then simply calculate the SHA-256 value of the unique string:

```
SHA256(unique-string)
= abcdef...12345678
```

You can then check the resulting hash against the signature value that was appened to the request:

- HTTP/HTTPS endpoint: `x-soracom-signature: abcdef...12345678`
- TCP/TCPS endpoint: `signature=abcdef...12345678`

## Air for Sigfox and Air for LoRaWAN

To use the **Signature header** option, you must create or select a **Pre-shared key**. The Sigfox or LoRa **Device ID** will automatically be used when calculating the SHA-256 signature.

When Beam receives data from your device, it will use the following information to generate a secure hash:

**Air for Sigfox** and **Air for LoRaWAN**

- Pre-shared key `{PSK}`
- Device ID `{DEVICE-ID}`
- Timestamp `{TS}`

This information is used to generate one the following unique strings:

- **Air for Sigfox** device:

  ```
  {PSK}x-soracom-sigfox-device-id={DEVICE-ID}x-soracom-timestamp={TS}
  ```

- **Air for LoRaWAN** device:

  ```
  {PSK}x-soracom-lora-device-id={DEVICE-ID}x-soracom-timestamp={TS}
  ```

Then simply calculate the SHA-256 value of the unique string:

```
SHA256(unique-string)
= abcdef...12345678
```

You can then check the resulting hash against the signature value that was appened to the request:

- HTTP/HTTPS endpoint: `x-soracom-signature: abcdef...12345678`
- TCP/TCPS endpoint: `signature=abcdef...12345678`

## Example

### Signature Generation

For example, given the following:

- Pre-shared key: `mysecretkey`
- Device IMEI: `860000012345678`
- Subscriber IMSI: `295000012345678`
- Timestamp: `1445587157992`

When a Beam HTTP/HTTPS endpoint is configured, the unique string will be formatted as:

```
mysecretkeyx-soracom-imei=860000012345678x-soracom-imsi=295000012345678x-soracom-timestamp=1445587157992
```

Then the signature header value is calculated using the unique string:

```
SHA256('mysecretkeyx-soracom-imei=860000012345678x-soracom-imsi=295000012345678x-soracom-timestamp=1445587157992')
= 95c8e34d68e2bd76502c1e403108dc1bd7008964c31081d0415adb9f21a721a5
```

---

### Signature Verification

When Beam sends data to the forwarding destination, the corresponding headers used in the SHA-256 calculation, excluding the Pre-shared key, will also be included as part of the HTTP/HTTPS request:

- `x-soracom-imei: 860000012345678`
- `x-soracom-imsi: 295000012345678`
- `x-soracom-timestamp: 1445587157992`
- `x-soracom-signature: 95c8e34d68e2bd76502c1e403108dc1bd7008964c31081d0415adb9f21a721a5`
- `x-soracom-signature-version: 20151001`

You can then combine the values from the headers together with your secret pre-shared key, using the either the HTTP/HTTPs format above, to independently verify the authenticity of the data.

## Test Server

When using the HTTPS Beam test server with the Signature header option enabled, you can test the signature calculation behavior.

Configure Beam for **HTTP entry point** using the following **Destination** parameters:

- **Protocol** - `HTTPS`
- **Host name** - `beamtest.soracom.io`
- **Port number** - `443` (or blank)

Then simply make an HTTP request from the device to `beam.soracom.io:8888`:

```bash
curl beam.soracom.io:8888

Hello SORACOM Beam Client 295000012345678 !

== HTTP Headers ==
HTTP_X_SORACOM_IMEI = 860000012345678
HTTP_X_SORACOM_IMSI = 295000012345678
HTTP_X_SORACOM_SIGNATURE = 95c8e34d68e2bd76502c1e403108dc1bd7008964c31081d0415adb9f21a721a5
HTTP_X_SORACOM_SIGNATURE_VERSION = 20151001
HTTP_X_SORACOM_TIMESTAMP = 1445587157992

= Signature Verification =
Pre shared key = mysecretkey

stringToSign:
x-soracom-imei=860000012345678x-soracom-imsi=295000012345678x-soracom-timestamp=1445587157992

calculated_signature:
SHA256('mysecretkey'+stringToSign) = 95c8e34d68e2bd76502c1e403108dc1bd7008964c31081d0415adb9f21a721a5

provided_signature:
95c8e34d68e2bd76502c1e403108dc1bd7008964c31081d0415adb9f21a721a5

signature:
Match!
```
