Unofficial Rust client for TÜBİTAK Kamu SM timestamp service.
Find a file
2026-02-13 16:31:06 +03:00
src refactor: certreq parametresi kaldırıldı 2025-09-27 22:18:53 +03:00
.gitignore feat: Rust ile Kamu SM zaman damgası istemcisi 2025-09-26 13:29:30 +03:00
Cargo.lock feat: Rust ile Kamu SM zaman damgası istemcisi 2025-09-26 13:29:30 +03:00
Cargo.toml feat: Rust ile Kamu SM zaman damgası istemcisi 2025-09-26 13:29:30 +03:00
README.md docs: İngilizce README bağlantısı 2026-02-13 16:31:06 +03:00
README_EN.md docs: README_EN eklendi 2026-02-13 16:29:53 +03:00

kamusm-zd-rs

🇹🇷 Türkçe

An RFC 3161 compliant Kamu SM (Turkish Public CA) timestamp client written in Rust, supporting Kamu SM's custom authentication protocol and compatible with the official Java client.

Table of Contents

Protocol Architecture

Kamu SM timestamp servers use the standard RFC 3161 TimeStampReq/TimeStampResp structure but require a custom identity header for authentication:

  • HTTP: POST / with application/timestamp-query
  • Body: RFC 3161 TimeStampReq (ASN.1 DER)
  • Authentication: User authentication via the identity header
  • Response: PKCS#7 SignedData with certificate

Identity Header

identity is the BigInteger hex representation of the DER encoding of the following ASN.1 structure:

ESYAReqEx ::= SEQUENCE {
    userid                 INTEGER,
    salt                   OCTET STRING (16 bytes),
    iterationCount         INTEGER (100),
    iv                     OCTET STRING (16 bytes, same as salt),
    encryptedMessageImprint OCTET STRING
}

Encryption Flow:

  1. 16-byte random value → used as both salt and IV
  2. PBKDF2-HMAC-SHA256(password, salt, 100 iterations) → 32-byte AES key
  3. AES-256-CBC(messageImprint, key, iv) + PKCS#7 padding → encrypted data
  4. ASN.1 structure → DER encoding → BigInteger → hex string

This prevents replay attacks by using a different salt/IV for each request.

Cryptography References

  • RFC 3161: Time-Stamp Protocol (RFC 3161)
  • PKCS#7: Public Key Cryptography Standards #7 (RFC 2315)
  • PKCS#7 SignedData: Digitally signed data structure (RFC 2315 Section 9.1)
  • ASN.1: Abstract Syntax Notation One - Data structure description notation (ITU-T X.680)
  • DER: Distinguished Encoding Rules - ASN.1 binary encoding rules (ITU-T X.690)
  • PBKDF2: Password-Based Key Derivation Function 2 (RFC 2898 Section 5.2)
  • HMAC: Hash-based Message Authentication Code (RFC 2104)
  • AES-256: Advanced Encryption Standard, 256-bit key length (FIPS 197)
  • CBC: Cipher Block Chaining mode (Wikipedia)

Requirements

  • Rust (tested with 1.85)
  • Cargo
  • A valid Kamu SM user account (customer ID and password)
  • Internet connection

Installation

Building from Source

# Clone the repository
git clone https://github.com/omerbustun/kamusm-zd-rs.git
cd kamusm-zd-rs

# Build
cargo build --release

# The executable will be created in target/release/

Running Directly

# Run in debug mode
cargo run -- --help

# Run in release mode
cargo run --release -- --help

Usage

Basic Command Structure

kamusm-zd-rs <COMMAND> [OPTIONS]

Requesting a Timestamp

Timestamp for a file

# SHA256 (recommended/default)
kamusm-zd-rs send \
    --host "http://zd.kamusm.gov.tr" \
    --customer-id 123 \
    --password "password" \
    --file document.txt \
    --hash sha256

# SHA1
kamusm-zd-rs send \
    --host "http://zd.kamusm.gov.tr" \
    --customer-id 123 \
    --password "password" \
    --file document.pdf \
    --hash sha1

Timestamp for a hex digest

kamusm-zd-rs send \
    --host "http://zd.kamusm.gov.tr" \
    --customer-id 123 \
    --password "password" \
    --digest-hex "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" \
    --hash sha256

Checking Credits

kamusm-zd-rs credits \
    --host "http://zd.kamusm.gov.tr" \
    --customer-id 123 \
    --password "password"

Generating an Identity Header

# With a hex digest
kamusm-zd-rs identity \
    --customer-id 123 \
    --password "password" \
    --digest-hex "abc123..."

# With a timestamp (for credit checks)
kamusm-zd-rs identity \
    --customer-id 123 \
    --password "password" \
    --timestamp 1635724800000

Configuration Options

Common Parameters

  • --host: Kamu SM timestamp server address
  • --customer-id: Customer ID number
  • --password: Customer password
  • --iterations: PBKDF2 iteration count (default: 100)

Send Command Parameters

  • --file: Path to the file to be timestamped
  • --digest-hex: Hash value directly in hex format
  • --hash: Hash algorithm (sha1 or sha256, default: sha256)

Output Files

  • File-based operations: {filename}_zd.der
  • Hex digest operations: zd_{timestamp}.der
  • Output files are in PKCS#7 SignedData format

Technical Implementation

Cryptographic Stack

  • Key Derivation: PBKDF2-HMAC-SHA256 (100 iterations, 32-byte key)
  • Symmetric Encryption: AES-256-CBC + PKCS#7 padding
  • ASN.1 Processing: DER encoding/decoding
  • Hash Algorithms: SHA1/SHA256 with OIDs, RFC 3161 compliant

MessageImprint Generation

  • Timestamp Request: File/data hash (SHA1/SHA256)
  • Credit Check: SHA1(customerID + timestamp_millis)
  • Authentication: In all cases, the relevant hash is encrypted and sent in the identity header

Error Handling

Kamu SM returns standard HTTP 200 for errors but includes error messages within the ASN.1 structure. The client looks for the PKCS#7 SignedData OID (1.2.840.113549.1.7.2):

  • Found: Valid timestamp, PKCS#7 is processed
  • Not found: ASN.1 is parsed to extract error messages from UTF8String/PrintableString fields

HTTP Request Format

POST / HTTP/1.1
Host: zd.kamusm.gov.tr
Content-Type: application/timestamp-query
User-Agent: kamusm-zd-rs
identity: <hex_encoded_ESYAReqEx>
Cache-Control: no-cache
Pragma: no-cache
Content-Length: <der_length>

<RFC3161_TimeStampReq_DER>

Examples

Successful Timestamp Request

$ kamusm-zd-rs send --host "http://zd.kamusm.gov.tr" --customer-id 123 --password "password" --file test.txt
Response status: 200 OK
Extracted PKCS#7 SignedData saved to test_zd.der

Verification with the Official Client

You can verify timestamps using Kamu SM's official Java console client:

Download: Kamu SM Software Platform - Zamane

$ java -jar tss-client-console-3.1.30.jar -c test.txt test_zd.der
[2025-Sep-27 16:04:45,054 PM] [INFO ] : File timestamp verification will be performed.
[2025-Sep-27 16:04:45,093 PM] [INFO ] : Timestamp is valid, file has not been modified.

Credit Check

$ kamusm-zd-rs credits --host "http://zd.kamusm.gov.tr" --customer-id 123 --password "password"
Response status: 200 OK
Remaining timestamp credits: 847

Error Case

$ kamusm-zd-rs send --host "http://zd.kamusm.gov.tr" --customer-id 999 --password "wrong"
Response status: 200 OK
Error response received (HTTP 200 OK)
Error messages:
  User 999 is not known

Common Errors

"Account could not be authenticated"

  • Incorrect user password

"User is not known"

  • Customer ID not found
  • Wrong customer number

Connection errors

  • Check the server address
  • Check your internet connection
  • Check firewall settings

Implementation Notes

Dependencies

  • yasna: ASN.1 DER encoding/decoding (ESYAReqEx, TimeStampReq generation)
  • aes + cbc: AES-256-CBC implementation (identity encryption)
  • pbkdf2 + hmac: Key derivation (PBKDF2-HMAC-SHA256)
  • reqwest: HTTP client (rustls-tls backend, suitable for blocking support/async wrapper)
  • num-bigint: Java BigInteger.toString(16) compatibility