api-signature

Crates.ioapi-signature
lib.rsapi-signature
version0.2.0
sourcesrc
created_at2022-01-31 23:40:27.787141
updated_at2022-04-21 13:26:04.677397
descriptionA library that helps make the signing of API transactions more simple and more schemantic
homepage
repositoryhttps://github.com/nebula-technologies/api-signature
max_upload_size
id524911
size26,448
Anders Blenstrup-Pedersen (KatsuoRyuu)

documentation

README

API Signature

pipeline status coverage report

A library for making API Signatures more schematic and reducing implementation overhead. The library helps build the desired API signing structure and ensures the validation will be done the same way across every service that uses the following library.

Prolog

Many systems today are using Logins and API-key to secure public APIs. Unfortunately, this is not true; when a user is authorized, the system sends an authorization token between the client and the server. If these tokens get hijacked, the malicious attacker can then parse payloads on behalf of the valid user. An API signature can help alleviate this problem.

Nonce

A nonce is a single-use ID that continuously increases, meaning one can never use the same ID again, and it needs always to be greater than the last. This ID is bound to the current API key and used to obscure the information sent between the server and the client.

Nonce a Lockdown security system

If an invalid nonce gets used, the API key should be blocked, and the system must require either a new API key created or the user must unblock the key. Nonce will secure the system by making sure an attack will be denied sending a falsified payload, and in case someone successfully tries to do it, there is a high chance that the application that initially was using the API key will end up blocking it.

Example

The attacker will likely use a large number as the nonce, causing the other client to send a lower number and get denied - blocking the key. At this point, the Hijacked tokens are no longer valid for use, and further illicit use will get denied.

##Usage

Defining an API structure

An API Structure can either be generated programatically or be imported from a configuration file. There are multiple available manipulators for the signing available:

Manipulator Function Description
HMAC SHA256 HmacSha256(Box<SignCal>[API enctyption key], Box<SignCal>[Data]) This will create a SHA256 HMAC1 using the API key and the data
HMAC SHA512 HmacSha512(Box<SignCal>[API enctyption key], Box<SignCal>[Data]) This will create a SHA512 HMAC1 using the API key and the data
SHA256 Sha256(Box<SignCal>) Encode data in SHA256 format
SHA512 Sha512(Box<SignCal>) Encode data in SHA512 format
Base64 Encoder Base64Encode(Box<SignCal>) Encode in Base64 format
Base64 Decoder Base64Decode(Box<SignCal>) Decode Base64
Base58 Encoder Base58Encode(Box<SignCal>) Encode in Base58 format
Base58 Decoder Base58Decode(Box<SignCal>) Decode Base58
Data Appending Append(Vec<SignCal>) Appending data together
String Joining JoinAsString(Vec<SignCal>) Treating the internal data as strings and joins them together
Data Variable from Raw VarData(String) Each signature will be passed a set of variables, this is for defining a variable where the expected data is raw &[u8]
Data Variable from String VarString(String) Each signature will be passed a set of variables, this is for defining a variable where the expected data is Text `string
Data Variable from Integer VarInteger(String) Each signature will be passed a set of variables, this is for defining a variable where the expected data is Number `i32
Raw Data Raw(Vec<u8>) This is not a variable, but directly inserted data. This can be used for salting by config

Configuration

In this configuration example we are using the default configuration that the library is supplying.

let config = Base64Encode(
    HmacSha512(
        Base64Decode(VarString("secret_key".to_string()).into()).into(),
        Append(vec![
            VarString("url".to_string()),
            Sha256(
                Append(vec![
                    VarInteger("nonce".to_string()),
                    JoinAsString(vec![
                        Raw("nonce=".to_string().into_bytes()),
                        VarInteger("nonce".to_string()),
                        Raw("&".to_string().into_bytes()),
                        VarString("payload".to_string()),
                    ]),
                ])
                .into(),
            ),
        ])
        .into(),
    )
);

This configuration takes 4 variables payload,secret_key, url, and nonce. these can be set by using the signature libraries .var([key], [data]).

Common usage

let nonce = 1616492376594usize;
let config = Base64Encode(
    HmacSha512(
        Base64Decode(VarString("secret_key".to_string()).into()).into(),
        Append(vec![
            VarString("url".to_string()),
            Sha256(
                Append(vec![
                    VarInteger("nonce".to_string()),
                    JoinAsString(vec![
                        Raw("nonce=".to_string().into_bytes()),
                        VarInteger("nonce".to_string()),
                        Raw("&".to_string().into_bytes()),
                        VarString("payload".to_string()),
                    ]),
                ])
                .into(),
            ),
        ])
        .into(),
    )
);
let mut signature = Signature::default();
signature.var("payload", format!("nonce={}&ordertype=limit&pair=XBTUSD&price=37500&type=buy&volume=1.25",nonce))
    .var("secret_key", "kQH5HW/8p1uGOVjbgWA7FunAmGO8lsSUXNsu3eow76sz84Q18fWxnyRzBHCd3pd5nE9qa99HAZtuZuj6F1huXg==")
    .var("url", "/0/private/AddOrder")
    .nonce(Arc::new(move || -> Vec<u8> {nonce.to_string().as_bytes().to_vec()}))
    .config();

let api_sign = b"4/dpxb3iT4tp/ZCVEwSnEsLxx0bqyhLpdfOpc6fn7OR8+UClSV5n9E6aSS8MPtnRfp32bAb0nmbRn6H8ndwLUQ==".to_vec();

assert_eq!(api_sign, signature.sign());

Footnotes

  1. HMAC: Hash-Based Message Authentication Codes 2

Commit count: 11

cargo fmt