NIST RSA-2048 PKCS#1 v1.5 SHA-256 Test Vector¶
Source: FIPS 186-3 RSA Test Vectors
Algorithm: RSASSA-PKCS1-v1_5 with SHA-256
Key Size: 2048 bits
Standard Exponent: e = 0x10001 (65537)
RSA Public Key (n, e)¶
e = 65537 (0x10001)
n = c83a19d579dd9b2a9ffb8ffb291f03de4867f9692e02686000f5e001b6cdba67be181cabfb841f6e85706889168b7b750639147853e3789b37080fb4d212997945779bd9ec3a94aa2657695fb4f5b6c541b3070ceb062ffb6d98669e46eac4b81bfb4bd38ed6b93e72e912de873205c89af64847d4546e1a541b4453f95d1d64a0e64f691cdfe1e8d755b16f8467be0cd2d904595e5fd35b4254b91015827dbfcfaa1cc48d31d53dce6066be11e3330bbb58ce1e4e6f7511cd4fa8a450050f97faaa6fdeb1afdc144219f135e9309b5f2706ff78456c3299029c1d5232ade2de93b9ae1108b4c43d008c56e6486ec32ed7eac339ddc5e5da50cbf53de1c98d55
RSA Private Key (d, p, q)¶
d = 26e0a6da963a8f90524056637938f103f7f00d8624472fd1620e66631098cda736c19e24a1cd5d07502c00fef1fc19152f351c7e1d3d81be637f4047684cb39f802f89c8be9bcd7e3940a5b498c536b9209c8523d8676d38de0d34c5607ccfca0b334ef803dd125392718db2b1cc24704f804173d31a233708c8bdf9d0a69600af72641b9db23115ba538cb4f5ef7d8c360096eebc377447a250d1ce167f361254c327bbdd4ead100c4c2be5db7adaf54f9124146404e44c2a4f810f6291c0ae96c423ad9f3467547cc57063e19d8122b84044d6268d4ccd276efe41068e1ac5bcdd8c0e303e70e6c23f0dc8703ce568e51cca7508beb38ae807e3d8c2050011
p = e8b6eb98eabc1637ea554660797d9e9ae6c1ccb1ce9bc1a3bcaae027f4b8ecafe4505b2f9fd2adcb467ae2a284adea757a74ae21988e14b1a2d2c9c392000bfd30673557818bfc91babfd5ee594ffadcd1466864cf30b9ccd43489a31f182caeed66b22343daffedee07244f04c6940fde856f1a101b19f1a40077d2a342b9e5
q = dc42ff716f6ee9c6f3d0eb2efb71e1d5567c7b3bc25a112ffa49850bc78f96b4a901ff82976e9974e777755c9775ccafb8102c5a69309a73f788aa54ea796a738197fb666c8be29596bf070ee687ab6f0aa21a70a0db60445e72d13ef9b88f8a40d9a0226f61c0d5a0442c0ddf74028d9a1d247afffb215ced3cbfa4c6c28eb1
Test Vector: Message → Signature¶
Hash Algorithm: SHA-256
Padding: PKCS#1 v1.5
Message (hex)¶
5af283b1b76ab2a695d794c23b35ca7371fc779e92ebf589e304c7f923d8cf976304c19818fcd89d6f07c8d8e08bf371068bdf28ae6ee83b2e02328af8c0e2f96e528e16f852f1fc5455e4772e288a68f159ca6bdcf902b858a1f94789b3163823e2d0717ff56689eec7d0e54d93f520d96e1eb04515abc70ae90578ff38d31b
Expected Signature (hex)¶
6b8be97d9e518a2ede746ff4a7d91a84a1fc665b52f154a927650db6e7348c69f8c8881f7bcf9b1a6d3366eed30c3aed4e93c203c43f5528a45de791895747ade9c5fa5eee81427edee02082147aa311712a6ad5fb1732e93b3d6cd23ffd46a0b3caf62a8b69957cc68ae39f9993c1a779599cdda949bdaababb77f248fcfeaa44059be5459fb9b899278e929528ee130facd53372ecbc42f3e8de2998425860406440f248d817432de687112e504d734028e6c5620fa282ca07647006cf0a2ff83e19a916554cc61810c2e855305db4e5cf893a6a96767365794556ff033359084d7e38a8456e68e21155b76151314a29875feee09557161cbc654541e89e42
Using with Trial API¶
The trial signing API uses this known RSA-2048 key for all requests. This lets you test signature verification without needing to manage credentials.
API Endpoint¶
POST https://services.leftcoastlogics.com/prod/trial/sign
Request¶
Send a JSON body with the message hash (base64-encoded SHA-256):
curl -X POST https://services.leftcoastlogics.com/prod/trial/sign \
-H "Content-Type: application/json" \
-d '{
"hash": "5af283b1b76ab2a695d794c23b35ca7371fc779e92ebf589e304c7f923d8cf976304c19818fcd89d6f07c8d8e08bf371068bdf28ae6ee83b2e02328af8c0e2f96e528e16f852f1fc5455e4772e288a68f159ca6bdcf902b858a1f94789b3163823e2d0717ff56689eec7d0e54d93f520d96e1eb04515abc70ae90578ff38d31b",
"algorithm": "RSASSA_PKCS1_V1_5_SHA_256",
"mode": "real"
}'
Request Fields:
hash(required): SHA-256 hash of your message, base64-encodedalgorithm(optional): Signing algorithm. Default:RSASSA_PKCS1_V1_5_SHA_256mode(optional):"real"for actual KMS signatures,"mock"for test placeholder. Default:"mock"
Response (Real Mode)¶
When mode: "real", the response contains the actual cryptographic signature:
{
"status": "success",
"mode": "real",
"algorithm": "RSASSA_PKCS1_V1_5_SHA_256",
"signature": "6b8be97d9e518a2ede746ff4a7d91a84a1fc665b52f154a927650db6e7348c69f8c8881f7bcf9b1a6d3366eed30c3aed4e93c203c43f5528a45de791895747ade9c5fa5eee81427edee02082147aa311712a6ad5fb1732e93b3d6cd23ffd46a0b3caf62a8b69957cc68ae39f9993c1a779599cdda949bdaababb77f248fcfeaa44059be5459fb9b899278e929528ee130facd53372ecbc42f3e8de2998425860406440f248d817432de687112e504d734028e6c5620fa282ca07647006cf0a2ff83e19a916554cc61810c2e855305db4e5cf893a6a96767365794556ff033359084d7e38a8456e68e21155b76151314a29875feee09557161cbc654541e89e42"
}
Response Fields:
status: Always"success"on valid requestsmode: Echo of the mode used ("real"or"mock")algorithm: Echo of the algorithm usedsignature: Hex-encoded RSA signature (256 bytes for 2048-bit keys)
Response (Mock Mode)¶
For testing without KMS calls, use mode: "mock":
{
"status": "success",
"mode": "mock",
"algorithm": "RSASSA_PKCS1_V1_5_SHA_256",
"signature": "TRIAL_MOCK_SIG_NOT_CRYPTOGRAPHICALLY_VALID_0000000000000000000000000000000000000000000000000000000000000000"
}
Verify the Signature with OpenSSL¶
Use OpenSSL to verify signatures returned by the trial API using the public key from this document:
1. Create a PEM file from the public key parameters¶
Create the public key PEM file using the n and e values from this document:
# Create a temporary script to generate the PEM file
python3 << 'PYTHON'
from Crypto.PublicKey import RSA
from Crypto.Util.number import inverse
# Public key parameters from this document
n = int('c83a19d579dd9b2a9ffb8ffb291f03de4867f9692e02686000f5e001b6cdba67be181cabfb841f6e85706889168b7b750639147853e3789b37080fb4d212997945779bd9ec3a94aa2657695fb4f5b6c541b3070ceb062ffb6d98669e46eac4b81bfb4bd38ed6b93e72e912de873205c89af64847d4546e1a541b4453f95d1d64a0e64f691cdfe1e8d755b16f8467be0cd2d904595e5fd35b4254b91015827dbfcfaa1cc48d31d53dce6066be11e3330bbb58ce1e4e6f7511cd4fa8a450050f97faaa6fdeb1afdc144219f135e9309b5f2706ff78456c3299029c1d5232ade2de93b9ae1108b4c43d008c56e6486ec32ed7eac339ddc5e5da50cbf53de1c98d55', 16)
e = 65537
# Create public key
key = RSA.construct((n, e))
# Export to PEM format
with open('public_key.pem', 'w') as f:
f.write(key.publickey().export_key().decode())
print("Public key saved to public_key.pem")
PYTHON
2. Verify a signature from the test vectors¶
# Use the provided test vector
MESSAGE_HEX="5af283b1b76ab2a695d794c23b35ca7371fc779e92ebf589e304c7f923d8cf976304c19818fcd89d6f07c8d8e08bf371068bdf28ae6ee83b2e02328af8c0e2f96e528e16f852f1fc5455e4772e288a68f159ca6bdcf902b858a1f94789b3163823e2d0717ff56689eec7d0e54d93f520d96e1eb04515abc70ae90578ff38d31b"
SIGNATURE_HEX="6b8be97d9e518a2ede746ff4a7d91a84a1fc665b52f154a927650db6e7348c69f8c8881f7bcf9b1a6d3366eed30c3aed4e93c203c43f5528a45de791895747ade9c5fa5eee81427edee02082147aa311712a6ad5fb1732e93b3d6cd23ffd46a0b3caf62a8b69957cc68ae39f9993c1a779599cdda949bdaababb77f248fcfeaa44059be5459fb9b899278e929528ee130facd53372ecbc42f3e8de2998425860406440f248d817432de687112e504d734028e6c5620fa282ca07647006cf0a2ff83e19a916554cc61810c2e855305db4e5cf893a6a96767365794556ff033359084d7e38a8456e68e21155b76151314a29875feee09557161cbc654541e89e42"
# Convert hex to binary files
echo -n "$MESSAGE_HEX" | xxd -r -p > message.bin
echo -n "$SIGNATURE_HEX" | xxd -r -p > signature.bin
# Verify the signature with OpenSSL
openssl dgst -sha256 -verify public_key.pem -signature signature.bin message.bin
Expected output: Verified OK
3. Verify a signature from the API¶
# 1. Get a signature from the trial API
HASH_B64=$(echo -n "5af283b1b76ab2a695d794c23b35ca7371fc779e92ebf589e304c7f923d8cf976304c19818fcd89d6f07c8d8e08bf371068bdf28ae6ee83b2e02328af8c0e2f96e528e16f852f1fc5455e4772e288a68f159ca6bdcf902b858a1f94789b3163823e2d0717ff56689eec7d0e54d93f520d96e1eb04515abc70ae90578ff38d31b" | xxd -r -p | base64)
RESPONSE=$(curl -s -X POST https://services.leftcoastlogics.com/prod/trial/sign \
-H "Content-Type: application/json" \
-d "{\"hash\": \"$HASH_B64\", \"mode\": \"real\"}")
# 2. Extract and verify the signature
SIGNATURE=$(echo "$RESPONSE" | jq -r '.signature')
echo -n "$SIGNATURE" | xxd -r -p > api_signature.bin
# 3. Verify using OpenSSL
echo -n "5af283b1b76ab2a695d794c23b35ca7371fc779e92ebf589e304c7f923d8cf976304c19818fcd89d6f07c8d8e08bf371068bdf28ae6ee83b2e02328af8c0e2f96e528e16f852f1fc5455e4772e288a68f159ca6bdcf902b858a1f94789b3163823e2d0717ff56689eec7d0e54d93f520d96e1eb04515abc70ae90578ff38d31b" | xxd -r -p > message.bin
openssl dgst -sha256 -verify public_key.pem -signature api_signature.bin message.bin
If successful, OpenSSL will print: Verified OK
Rate Limits¶
Trial endpoint is rate-limited to 10 requests per hour per IP address. Useful for prototyping and testing integrations without requiring credentials.
Example: Complete Test¶
Prerequisites:
curl- for API callsopenssl- for signature verificationbase64- for encoding (standard on Linux/macOS)grep,sed- for JSON parsing (POSIX standard)public_key.pem- generated from step 1 above
Copy-paste script (POSIX-compatible):
#!/bin/sh
set -e # Exit on any error
# Configuration
API_URL="https://services.leftcoastlogics.com/prod/trial/sign"
PUBLIC_KEY_FILE="public_key.pem"
# Check dependencies
for cmd in curl openssl base64 grep sed; do
if ! command -v "$cmd" >/dev/null 2>&1; then
echo "Error: Required command '$cmd' not found. Please install it."
exit 1
fi
done
# Verify public key exists
if [ ! -f "$PUBLIC_KEY_FILE" ]; then
echo "Error: $PUBLIC_KEY_FILE not found. Generate it using the Python script from step 1."
exit 1
fi
echo "=== SaaS Signer Trial API Test ==="
echo ""
# 1. Create a test message and compute SHA-256 hash
MESSAGE="Hello, SaaS Signer!"
HASH_HEX=$(printf '%s' "$MESSAGE" | sha256sum | cut -d' ' -f1)
echo "Message: $MESSAGE"
echo "Hash (hex): $HASH_HEX"
echo ""
# 2. Convert hex to base64 (for API input)
# Using printf and od for POSIX compatibility (no xxd needed)
HASH_B64=$(printf '%s' "$HASH_HEX" | sed 's/../\\x&/g' | xargs printf '%b' | base64 | tr -d '\n')
# 3. Call the trial endpoint in real mode
echo "Calling trial API..."
RESPONSE=$(curl -s -X POST "$API_URL" \
-H "Content-Type: application/json" \
-d "{\"hash\": \"$HASH_B64\", \"mode\": \"real\"}")
# 4. Extract signature from JSON (POSIX: using grep and sed, no jq needed)
SIGNATURE=$(echo "$RESPONSE" | grep -o '"signature":"[^"]*' | sed 's/"signature":"//')
if [ -z "$SIGNATURE" ]; then
echo "Error: Failed to get signature. Response: $RESPONSE"
exit 1
fi
echo "Signature received: ${SIGNATURE:0:32}... (truncated)"
echo ""
# 5. Verify the signature with OpenSSL
echo "Verifying signature with OpenSSL..."
# Create temporary files (more portable than process substitution)
TMPDIR="${TMPDIR:-/tmp}"
HASH_FILE=$(mktemp "$TMPDIR/hash.XXXXXX")
SIG_FILE=$(mktemp "$TMPDIR/sig.XXXXXX")
trap "rm -f '$HASH_FILE' '$SIG_FILE'" EXIT
# Convert hex strings to binary
printf '%s' "$HASH_HEX" | sed 's/../\\x&/g' | xargs printf '%b' > "$HASH_FILE"
printf '%s' "$SIGNATURE" | sed 's/../\\x&/g' | xargs printf '%b' > "$SIG_FILE"
# Verify
if openssl dgst -sha256 -verify "$PUBLIC_KEY_FILE" -signature "$SIG_FILE" "$HASH_FILE"; then
echo "✓ Signature verified successfully!"
else
echo "✗ Signature verification failed!"
exit 1
fi
Quick version (Bash/Zsh only, if xxd and jq available):
#!/bin/bash
MESSAGE="Hello, SaaS Signer!"
HASH_HEX=$(printf '%s' "$MESSAGE" | sha256sum | cut -d' ' -f1)
HASH_B64=$(printf '%s' "$HASH_HEX" | xxd -r -p | base64 | tr -d '\n')
RESPONSE=$(curl -s -X POST https://services.leftcoastlogics.com/prod/trial/sign \
-H "Content-Type: application/json" \
-d "{\"hash\": \"$HASH_B64\", \"mode\": \"real\"}")
SIGNATURE=$(echo "$RESPONSE" | jq -r '.signature')
echo "Message: $MESSAGE"
echo "Hash: $HASH_HEX"
echo "Signature: $SIGNATURE"
echo ""
openssl dgst -sha256 -verify public_key.pem \
-signature <(printf '%s' "$SIGNATURE" | xxd -r -p) \
<(printf '%s' "$HASH_HEX" | xxd -r -p)
Source¶
- File:
external/186-3rsatestvectors/KeyGen_186-3.rsp - File:
external/186-3rsatestvectors/SigGen15_186-3.rsp - Standard: FIPS 186-3 (Digital Signature Standard)
- Program: NIST CAVS 11.1 / CAVP (Cryptographic Algorithm Validation Program)
Security Note: These are official NIST test vectors published for validation purposes. Do NOT use these keys in production. They are well-known and published for testing only.