# How DS2API Implements DeepSeek Proof of Work (PoW): A Complete Technical Guide

> Learn how DS2API implements DeepSeek Proof of Work (PoW) using a native Go package to brute-force SHA-3-256 hashes for API security. Get the technical details.

- Repository: [CJACK./ds2api](https://github.com/CJackHwang/ds2api)
- Tags: deep-dive
- Published: 2026-04-26

---

**DS2API implements DeepSeek Proof of Work through a native Go package that brute-forces SHA-3-256 hashes using a custom 23-round Keccak permutation to generate valid `x-ds-pow-response` headers for protected API endpoints.**

The [CJackHwang/ds2api](https://github.com/CJackHwang/ds2api) repository provides a production-ready Go implementation of DeepSeek's Proof of Work protocol. This self-contained solution eliminates external cryptographic dependencies while delivering deterministic cross-platform behavior for solving server-issued challenges.

## Understanding the Challenge Structure

DeepSeek's API issues PoW challenges as JSON objects containing cryptographic parameters. The [`pow/deepseek_pow.go`](https://github.com/CJackHwang/ds2api/blob/main/pow/deepseek_pow.go) file defines the `Challenge` struct that captures these server requirements:

```go
type Challenge struct {
    Algorithm  string `json:"algorithm"`   // Only "DeepSeekHashV1" is supported
    Challenge  string `json:"challenge"`   // 64-char hex target hash
    Salt       string `json:"salt"`        // Random per-request salt
    ExpireAt   int64  `json:"expire_at"`   // Unix timestamp when challenge expires
    Difficulty int64  `json:"difficulty"`  // Max nonce to try (default 144000)
    Signature  string `json:"signature"`   // Server-signed data
    TargetPath string `json:"target_path"` // Protected endpoint path
}

```

The **prefix construction** determines the input data hashed during solving. The `BuildPrefix` function concatenates the salt, expiration timestamp, and delimiters into a fixed string absorbed before the nonce:

```go
func BuildPrefix(salt string, expireAt int64) string {
    return salt + "_" + strconv.FormatInt(expireAt, 10) + "_"
}

```

## The DeepSeekHashV1 Algorithm

DS2API implements **DeepSeekHashV1** in [`pow/deepseek_hash.go`](https://github.com/CJackHwang/ds2api/blob/main/pow/deepseek_hash.go) as a modified SHA-3-256 hash that skips the initial Keccak round. This pure-Go implementation mirrors DeepSeek's WebAssembly reference (`wasm_deepseek_hash_v1`) exactly.

The algorithm operates through four distinct phases:

1. **State initialization**: Creates a 25-word uint64 array (`[25]uint64`) representing the Keccak-f[1600] state
2. **Data absorption**: Processes input in 136-byte blocks (the SHA-3-256 rate) using the custom permutation
3. **Custom permutation**: Executes the `keccakF23` function performing **23 rounds** (rounds 1-23, omitting round 0) of the standard Keccak-f transformation
4. **Digest extraction**: Applies standard SHA-3 padding (`0x06` suffix and `0x80` final byte) before extracting the first four 64-bit words as the 32-byte digest

```go
func DeepSeekHashV1(data []byte) [32]byte {
    // Implementation handles 23-round Keccak-f[1600] without external dependencies
    // Returns deterministic 32-byte hash matching DeepSeek's WebAssembly output
}

```

## Solving the PoW Challenge

The `SolvePow` function in [`pow/deepseek_pow.go`](https://github.com/CJackHwang/ds2api/blob/main/pow/deepseek_pow.go) performs a deterministic brute-force search across the nonce space `[0, difficulty)` to find a value satisfying:

```

DeepSeekHashV1(BuildPrefix(salt, expireAt) || decimal(nonce)) == challenge_target

```

The solver implements several performance optimizations:

- **Pre-absorption**: Computes the Keccak state for the prefix once, storing it in `baseState` to avoid reprocessing fixed data for every nonce attempt
- **Incremental hashing**: Appends each candidate nonce's decimal ASCII representation to the absorbed prefix state
- **Cancellation support**: Checks the provided `context.Context` every 1024 iterations to enable responsive timeout handling
- **Little-endian comparison**: Decodes the 64-character hex target into four uint64 words (`t0` through `t3`) for direct state comparison

If the search exhausts the difficulty bound without finding a match, the function returns an error indicating no solution exists within the constraints.

## Constructing the Response Header

Once a valid nonce is discovered, `BuildPowHeader` serializes the solution into the Base64-encoded JSON format expected by DeepSeek's API:

```go
func BuildPowHeader(c *Challenge, answer int64) (string, error) {
    payload, err := json.Marshal(map[string]any{
        "algorithm":   c.Algorithm,
        "challenge":   c.Challenge,
        "salt":        c.Salt,
        "answer":      answer,
        "signature":   c.Signature,
        "target_path": c.TargetPath,
    })
    if err != nil {
        return "", err
    }
    return base64.StdEncoding.EncodeToString(payload), nil
}

```

The convenience wrapper `SolveAndBuildHeader` orchestrates the entire workflow:

```go
func SolveAndBuildHeader(ctx context.Context, c *Challenge) (string, error) {
    if c.Algorithm != "DeepSeekHashV1" {
        return "", errors.New("pow: unsupported algorithm: " + c.Algorithm)
    }
    difficulty := c.Difficulty
    if difficulty == 0 {
        difficulty = 144000 // Fallback default difficulty
    }
    answer, err := SolvePow(ctx, c.Challenge, c.Salt, c.ExpireAt, difficulty)
    if err != nil {
        return "", err
    }
    return BuildPowHeader(c, answer)
}

```

The resulting Base64 string must be attached to subsequent requests as the **`x-ds-pow-response`** HTTP header.

## Practical Implementation Examples

### Solving a Real-Time Challenge from DeepSeek API

This example demonstrates fetching a challenge, solving it with context cancellation support, and attaching the header to a protected request:

```go
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "time"

    "github.com/CJackHwang/ds2api/pow"
)

func main() {
    // Fetch PoW challenge from DeepSeek endpoint
    resp, err := http.Get("https://api.deepseek.com/v0/chat/create_pow_challenge")
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()
    
    body, _ := io.ReadAll(resp.Body)

    var challenge pow.Challenge
    if err := json.Unmarshal(body, &challenge); err != nil {
        panic(err)
    }

    // Solve with 10-second timeout
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()

    headerValue, err := pow.SolveAndBuildHeader(ctx, &challenge)
    if err != nil {
        panic(err) // Handles timeout or no-solution cases
    }

    // Attach header to protected request
    req, _ := http.NewRequest("POST", "https://api.deepseek.com/v0/chat/completions", nil)
    req.Header.Set("x-ds-pow-response", headerValue)
    req.Header.Set("Content-Type", "application/json")
    
    client := &http.Client{}
    protectedResp, _ := client.Do(req)
    fmt.Println("Protected endpoint status:", protectedResp.Status)
}

```

### Custom Difficulty and Manual Nonce Verification

For servers requiring higher work factors or custom verification:

```go
// Increase difficulty beyond default 144000
challenge.Difficulty = 500_000

ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

header, err := pow.SolveAndBuildHeader(ctx, &challenge)
if err != nil {
    fmt.Printf("PoW solving failed: %v\n", err)
    return
}

// The header contains base64-encoded JSON with the answer field
fmt.Printf("Generated PoW header: %s\n", header)

```

## Summary

- **DS2API** provides a zero-dependency Go implementation of DeepSeek's Proof of Work in the `pow` package
- **DeepSeekHashV1** uses a modified SHA-3-256 with 23 Keccak rounds (skipping round 0), implemented in [`pow/deepseek_hash.go`](https://github.com/CJackHwang/ds2api/blob/main/pow/deepseek_hash.go)
- The **Challenge struct** in [`pow/deepseek_pow.go`](https://github.com/CJackHwang/ds2api/blob/main/pow/deepseek_pow.go) captures server requirements including difficulty, salt, and expiration timestamps
- **SolvePow** optimizes performance through prefix pre-absorption and context-aware cancellation checks every 1024 iterations
- **SolveAndBuildHeader** generates the `x-ds-pow-response` header by Base64-encoding a JSON payload containing the discovered nonce

## Frequently Asked Questions

### What makes DeepSeekHashV1 different from standard SHA-3-256?

DeepSeekHashV1 omits the first round of the standard Keccak-f[1600] permutation. While SHA-3-256 uses 24 rounds (rounds 0-23), DeepSeek's implementation executes only 23 rounds (rounds 1-23). This subtle modification requires custom cryptographic code, as standard libraries cannot configure the starting round index. DS2API's [`pow/deepseek_hash.go`](https://github.com/CJackHwang/ds2api/blob/main/pow/deepseek_hash.go) implements this precisely to match DeepSeek's WebAssembly reference.

### How does DS2API handle high-difficulty PoW challenges efficiently?

The solver optimizes through state pre-absorption. Rather than re-hashing the entire prefix (salt + timestamp + delimiter) for every nonce attempt, `SolvePow` computes the Keccak state after absorbing the prefix once, then clones this base state for each candidate nonce. This reduces the per-iteration workload significantly when searching large nonce spaces up to the default difficulty of 144,000 or higher.

### Can the PoW solver be cancelled mid-computation?

Yes. The `SolvePow` function accepts a `context.Context` parameter and checks for cancellation every 1024 iterations. This allows applications to enforce strict timeouts or respond to shutdown signals without leaking goroutines. If the context is cancelled before a solution is found, the function immediately returns the context error.

### Where does DS2API validate the PoW challenge signature?

While the `Challenge` struct includes a `Signature` field for server-signed data, the core `pow` package focuses on solving valid challenges rather than cryptographic verification of the signature itself. According to the source structure, signature validation likely occurs in upstream handlers such as [`api/index.go`](https://github.com/CJackHwang/ds2api/blob/main/api/index.go) before the challenge reaches the solver, ensuring only authentic challenges consume computational resources.