Signature - chữ kí điện tử

Mô tả về chữ kí điện tử để xác thực dữ liệu.

VinID sử dụng chữ ký điện tử (signature) để xác thực dữ liệu đầu vào và ra trên mỗi HTTP Request.

Hệ thống VinID sử dụng thuật toán SHA256 RSA ( key size = 2048 bit) để tạo signature.

Tạo chữ ký điện tử

openssl genrsa -out RS256-2048-Private.rsa 2048
openssl rsa -in RS256-2048-Private.rsa -pubout > RS256-2048-Public.rsa

Format chữ ký điện tử

  • PrivateKey: do merchant tự generate ra theo định dạng SHA256 RSA ( 2048 )

  • URL: Endpoint API

RawData = {url};{method};{X-Nonce};{X-Timestamp};{X-Key-Code};{body}
X-Signature = ​SHA256WithRSA(PrivateKey, RawData)

Ví dụ:

url: '/merchant-integration/v1/qr/gen-transaction-qr'
method: 'POST'
X-Nonce: '00a81e60-2684-4cf9-878d-f37559213059'
X-Timestamp: 1570723375
X-Key-Code: 'b7bdf002-4948-44d2-99d1-99c8c81c3f47'
Body: {"callback_url":"https://webhook.site/17d9577f-70ca-4918-8388-1d6d53d8bc69","description":"Kiểm thử thanh toán","order_amount":10000,"order_currency":"VND","pos_code":"IPOS002","service_type":"PURCHASE","store_code":"ISTORE002"}
RawData: /merchant-integration/v1/qr/gen-transaction-qr;POST;00a81e60-2684-4cf9-878d-f37559213059;1570723375;b7bdf002-4948-44d2-99d1-99c8c81c3f47;{"callback_url":"https://webhook.site/17d9577f-70ca-4918-8388-1d6d53d8bc69","description":"Kiểm thử thanh toán","order_amount":10000,"order_currency":"VND","pos_code":"IPOS002","service_type":"PURCHASE","store_code":"ISTORE002"}
X-Signature: SHA256WithRSA(PrivateKey, RawData)
=> X-Signature: ERSt3cZoijwJf8QIZdcpHPygcDQJ+tA7l/2EVyJyhO8fwpp6mbrYWsyhyqDjD4zkhGwcXVJ7zJQUDWFpCPitG9GlmssEnkp57YK94/6GR54x6COzPqOlJjoQ4Lq6Fvw99QVmjiL+WjGWSOTUkusXh9dr871vCrjcYmyFSCZ9Ydfw6l4iv2evOnibUtalIkdsNM6evrVa7qW28Uno5t8fmz68QJeXd0dqL4lm2tsFAr9094jbWh/zlynqAW9MOIIYjXQC7XwEVKiBEmoZyTnSd8SLITLNIXvLCJjjVT5XYqZAMNIyoNYZKom8dUjLuirBBurcUpXuxlu01O8dU9qHdg==

Code mẫu tạo Signature

// GenerateSignature util to generate signature form Auth Claim of merchant
func GenerateSignature(claim *dtos.AuthClaims, privKey []byte) (string, error) {
    block, _ := pem.Decode(privKey)
    privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
    if err != nil {
        fmt.Printf("Error ParsePKCS1PrivateKey: %v", err)
        return "", err
    }
    hash := generateHash(claim.URL, claim.Method, claim.Nonce, claim.Timestamp, claim.KeyCode, claim.Body)
    signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hash[:])
    if err != nil {
        fmt.Printf("Error from signing: %s\n", err)
        return "", err
    }
    claim.Signature = base64.StdEncoding.EncodeToString(signature)
    return claim.Signature, nil
}

Last updated