Information Security 26 min read

Secure OpenAPI Design: AppId/AppSecret, RSA Signatures, Timestamp & Nonce Best Practices

This article explains how to secure OpenAPI interfaces by using globally unique AppId/AppSecret pairs, SHA‑256 and RSA signatures, timestamp and nonce validation, caching, rate‑limiting, parameter validation, and encryption algorithms, providing complete client‑server implementation examples in Java.

Architect
Architect
Architect
Secure OpenAPI Design: AppId/AppSecret, RSA Signatures, Timestamp & Nonce Best Practices

The OpenAPI specification standardizes API contracts, improves reusability, and enhances security; this guide introduces practical measures such as using a globally unique AppId paired with an AppSecret to generate signed requests.

AppId usage : AppId identifies the caller, while AppSecret acts as a password. Both are combined to create a signature that is encrypted and verified on the server side.

Signature generation : The client first hashes request parameters with SHA‑256 to obtain sign , then assembles all parameters (including AppId , nonce , timestamp ) in alphabetical order, appends AppSecret , and signs the string with RSA using SHA256withRSA . The resulting appSign is sent in the request header.

String sign = getSHA256Str(JSONObject.toJSONString(userEntity));
Map
data = new HashMap<>();
data.put("appId", appId);
data.put("nonce", nonce);
data.put("sign", sign);
data.put("timestamp", timestamp);
StringBuilder sb = new StringBuilder();
for (String k : sortedKeys) {
    if (data.get(k).trim().length() > 0) {
        sb.append(k).append("=").append(data.get(k).trim()).append("&");
    }
}
sb.append("appSecret=").append(appSecret);
String appSign = sha256withRSASignature(privateKey, sb.toString());

Server verification : The server recomputes the SHA‑256 hash of the body, validates the sign , reconstructs the signed string, and verifies the RSA signature with the stored public key. It also checks that the timestamp is within a 5‑minute window and that the nonce has not been used before (using a Guava cache or Redis).

long now = System.currentTimeMillis();
if ((now - Long.parseLong(timestamp)) / 1000 / 60 >= 5) {
    throw new Exception("Request expired!");
}
String cacheKey = appId + "_" + nonce;
if (cache.getIfPresent(cacheKey) != null) {
    throw new Exception("Replay attack!");
}
cache.put(cacheKey, "1");
if (!rsaVerifySignature(sb.toString(), publicKey, header.getAppSign())) {
    throw new Exception("Signature verification failed!");
}

Additional protective measures include access‑control based on AppId , strict parameter validation using Spring Boot Validation annotations, rate limiting with Guava RateLimiter or Redis/Sentinel, and data‑masking for sensitive fields.

The article also reviews cryptographic fundamentals such as MD5 (with salting), symmetric algorithms (DES, 3DES, AES in ECB/CBC modes), and their security implications, providing concise Java examples for each.

Finally, it offers practical advice on API documentation, error handling, versioning, and extensibility to ensure a robust, maintainable, and secure API ecosystem.

JavaAuthenticationRSAAPI securitySignatureOpenAPI
Architect
Written by

Architect

Professional architect sharing high‑quality architecture insights. Topics include high‑availability, high‑performance, high‑stability architectures, big data, machine learning, Java, system and distributed architecture, AI, and practical large‑scale architecture case studies. Open to ideas‑driven architects who enjoy sharing and learning.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.