> For the complete documentation index, see [llms.txt](https://a-send.gitbook.io/api/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://a-send.gitbook.io/api/auth/signature.md).

# 전자서명

### **알고리즘**

서명은 **HMAC-SHA256** 알고리즘으로 생성하며, 결과를 **Base64** 인코딩합니다.

### **페이로드 구성**

아래 4개의 값을 줄바꿈(`\n`)으로 연결한 페이로드를 API Secret으로 HMAC-SHA256 해싱 후 Base64 인코딩합니다.

{% code title="페이로드 구성" fullWidth="false" %}

```
{METHOD}\n{PATH}\n{TIMESTAMP}\n{BODY_HASH}
```

{% endcode %}

<table><thead><tr><th width="78">순서</th><th width="156">요소</th><th width="330">설명</th><th>예시</th></tr></thead><tbody><tr><td>1</td><td><code>METHOD</code></td><td>HTTP 메서드 (대문자)</td><td><code>POST</code></td></tr><tr><td>2</td><td><code>PATH</code></td><td>요청 경로 (쿼리스트링 제외)</td><td><code>/v1/message/send</code></td></tr><tr><td>3</td><td><code>TIMESTAMP</code></td><td>Authorization 헤더의 <code>ts</code> 값</td><td><code>1707800000</code></td></tr><tr><td>4</td><td><code>BODY_HASH</code></td><td>요청 본문의 SHA-256 해시 (hex)</td><td><code>a1b2c3d4...</code></td></tr></tbody></table>

{% hint style="warning" %}
요청 본문이 비어있더라도(GET 요청 등) 빈 문자열(`""`)을 SHA-256 해싱해야 합니다.
{% endhint %}

### **생성 절차**

{% stepper %}
{% step %}

### 페이로드 조합

```
payload = "POST\n/v1/message/send\n1707800000\n{body의 SHA-256 해시}"
```

{% endstep %}

{% step %}

### HMAC-SHA256 해싱

```
hmac = HMAC-SHA256(payload, {API_SECRET})
```

{% endstep %}

{% step %}

### Base64  인코딩

```
signature = Base64Encode(hmac)
```

{% endstep %}
{% endstepper %}

### **언어별 구현 예시**

{% tabs %}
{% tab title="Java" %}

```java
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;
import java.util.Base64;

String timestamp = String.valueOf(System.currentTimeMillis() / 1000);

MessageDigest digest = MessageDigest.getInstance("SHA-256");
String bodyHash = bytesToHex(digest.digest(body.getBytes("UTF-8")));

String payload = String.join("\n", method.toUpperCase(), path, timestamp, bodyHash);

Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(apiSecret.getBytes("UTF-8"), "HmacSHA256"));
String signature = Base64.getEncoder().encodeToString(mac.doFinal(payload.getBytes("UTF-8")));
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
$body = json_encode($requestData);
$timestamp = time();

$payload =
    strtoupper($method) . "\n" .
    $path . "\n" .
    $timestamp . "\n" .
    hash('sha256', $body);

$signature = base64_encode(
    hash_hmac('sha256', $payload, $apiSecretKey, true)
);
```

{% endtab %}

{% tab title="Python" %}

```python
import hmac, hashlib, base64, json, time

body = json.dumps(request_data)
timestamp = str(int(time.time()))

payload = "\n".join([
    method.upper(),
    path,
    timestamp,
    hashlib.sha256(body.encode()).hexdigest()
])

signature = base64.b64encode(
    hmac.new(api_secret.encode(), payload.encode(), hashlib.sha256).digest()
).decode()
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const crypto = require('crypto');

const body = JSON.stringify(requestData);
const timestamp = Math.floor(Date.now() / 1000).toString();

const payload = [
  method.toUpperCase(),
  path,
  timestamp,
  crypto.createHash('sha256').update(body).digest('hex')
].join('\n');

const signature = crypto
  .createHmac('sha256', apiSecret)
  .update(payload)
  .digest('base64');
```

{% endtab %}
{% endtabs %}

<br>
