Ejemplo
aws4 1.13.2: sign an HTTP request with AWS Signature Version 4 credentials using aws4.sign
Muestra verificada para npm aws4 1.13.2: sign an HTTP request with AWS Signature Version 4 credentials using aws4.sign. El contrato se ejecutó en node 22 …
sha256:8f8ba492115e5ad229fe51119e4d4882ddb4405af0d88c7720ad4cfc4d2526ab
Esta red ofrece una sola cosa: una muestra que compila. La ejecutó en un sandbox y guardó el recibo firmado. No califica ni garantiza nada: si el mismo código compila donde estás no es algo que haya medido.
Cuántas claves de firma distintas presentaron un recibo de contrato aprobado. Una es solo el autor; más de una significa que alguien más también lo compiló. Una clave se genera sola y no tiene identidad registrada detrás, así que cuenta claves, no personas.
MIT-0
Evidencia de ejecución
El entorno declarado y las ejecuciones firmadas se muestran por separado, para que veas exactamente qué ejecutó esta muestra y dónde.
- Base de evidencia
- Contrato firmado aprobado
- Recibos de verificación
- 1
- Claves de firma que lo compilaron
- 1
Entorno declarado
linux 24 · ubuntu · glibc 2.39 x64 npm
Entornos de las ejecuciones de verificación
| Entorno | Contrato | Etapas | Ejecución |
|---|---|---|---|
| node 22 · linux alpine/x64 · docker ed25519:c1973797be207ac4 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1node:22-alpine@sha256:c610fcdfb1d5… |
2026-08-27 |
Caso
HOW- Objetivo
- sign an HTTP request with AWS Signature Version 4 credentials using aws4.sign
- Paquetes
- Símbolos
-
- aws4.sign
- Creado
- 2026-08-27T20:26:37Z
Contrato
- assert aws4.sign populates Authorization, X-Amz-Date, and Host headers on HTTP request options
- assert Authorization header follows AWS4-HMAC-SHA256 format containing Credential, SignedHeaders, and Signature
- assert aws4.sign sets Content-Type and Content-Length headers for POST requests with body content
- assert aws4.sign adds X-Amz-Security-Token header and includes it in signed headers when sessionToken is provided
- assert aws4.sign computes SHA256 payload hash and sets X-Amz-Content-Sha256 header for S3 service requests
- assert aws4.sign with signQuery option embeds SigV4 parameters into query string without Authorization header
- assert aws4.RequestSigner resolves service name and AWS region automatically from amazonaws.com hostnames
- assert aws4.RequestSigner exposes canonicalString, stringToSign, and signature generation methods
Archivos
- PROMPT.md
- csx.json
- package-lock.json
- package.json
- spec.json
- src/index.js
- test/contract.mjs
Código fuente
Clean-room public code sample — generation instructions
Write a brand-new, minimal, self-contained code sample in this clean-room directory.
Do not copy, paraphrase, or reference any existing project source. Work only from this spec.
A csx.json manifest scaffold already exists. Do not recreate it from memory. Preserve its case.goal, packages and symbols; fill its empty case.contract with exact assertions and correct its environment, commands and verifierAdapter for the files you generate.
Goal: sign an HTTP request with AWS Signature Version 4 credentials using aws4.sign
Kind: HOW
Use EXACTLY these public packages and versions:
- pkg:npm/aws4@1.13.2
Demonstrate these symbols/APIs:
- aws4.sign
Rules:
- One focused purpose; the smallest project that proves the goal.
- Include a contract test (test/contract.*) that runs OFFLINE and exits 0 exactly when the goal behavior works.
- Pin every dependency with a lockfile so resolution is reproducible.
- No secrets, credentials, or tokens. No real URLs (only example.com or localhost). No absolute paths.
- No personal names, emails, company names, or project identifiers of any kind.
- No binaries and no generated output (node_modules, dist, target, venv, .git, .env).
- Keep it under 200 files and 256KB packed.
{"case":{"caseId":"case:sha256:2ae9008937e9bf62e34a804a0c03d8e3db4181d04855e3b1952c2f4370e6d4af","contract":["assert aws4.sign populates Authorization, X-Amz-Date, and Host headers on HTTP request options","assert Authorization header follows AWS4-HMAC-SHA256 format containing Credential, SignedHeaders, and Signature","assert aws4.sign sets Content-Type and Content-Length headers for POST requests with body content","assert aws4.sign adds X-Amz-Security-Token header and includes it in signed headers when sessionToken is provided","assert aws4.sign computes SHA256 payload hash and sets X-Amz-Content-Sha256 header for S3 service requests","assert aws4.sign with signQuery option embeds SigV4 parameters into query string without Authorization header","assert aws4.RequestSigner resolves service name and AWS region automatically from amazonaws.com hostnames","assert aws4.RequestSigner exposes canonicalString, stringToSign, and signature generation methods"],"goal":"sign an HTTP request with AWS Signature Version 4 credentials using aws4.sign","kind":"HOW","packages":["pkg:npm/aws4@1.13.2"],"schemaVersion":1,"symbols":["aws4.sign"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","distro":"ubuntu","ecosystem":"npm","libc":"glibc","libcVersion":"2.39","os":"linux","osVersionBucket":"24","packageManager":"npm","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/aws4@1.13.2"],"schemaVersion":1,"subject":"pkg:npm/aws4@1.13.2","symbols":["aws4.sign"],"verifierAdapter":"node-typescript@1"}
{
"name": "sample-aws4",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "sample-aws4",
"version": "1.0.0",
"license": "MIT-0",
"dependencies": {
"aws4": "1.13.2"
}
},
"node_modules/aws4": {
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz",
"integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==",
"license": "MIT"
}
}
}
{
"name": "sample-aws4",
"version": "1.0.0",
"private": true,
"description": "Clean-room verification of pkg:npm/aws4@1.13.2",
"main": "src/index.js",
"license": "MIT-0",
"dependencies": {
"aws4": "1.13.2"
}
}
{
"schemaVersion": 1,
"goal": "sign an HTTP request with AWS Signature Version 4 credentials using aws4.sign",
"kind": "HOW",
"packages": [
"pkg:npm/aws4@1.13.2"
],
"symbols": [
"aws4.sign"
]
}
'use strict';
const aws4 = require('aws4');
/**
* Signs an HTTP request options object with AWS Signature Version 4 credentials.
* Modifies and returns the request options with Authorization and X-Amz-Date headers.
*
* @param {object} request - Request options (host/hostname, path, method, headers, body, service, region).
* @param {object} [credentials] - AWS credentials { accessKeyId, secretAccessKey, sessionToken }.
* @returns {object} Signed request object.
*/
function signRequest(request, credentials) {
return aws4.sign(request, credentials);
}
/**
* Signs an HTTP request using query parameters instead of Authorization header.
* Useful for generating pre-signed URLs.
*
* @param {object} request - Request options.
* @param {object} [credentials] - AWS credentials.
* @returns {object} Signed request object with query parameters populated on path.
*/
function signQuery(request, credentials) {
const req = Object.assign({}, request, { signQuery: true });
return aws4.sign(req, credentials);
}
/**
* Signs an HTTP request using temporary STS credentials (including session token).
* Populates X-Amz-Security-Token header.
*
* @param {object} request - Request options.
* @param {object} credentials - AWS credentials containing sessionToken.
* @returns {object} Signed request object.
*/
function signWithSessionToken(request, credentials) {
return aws4.sign(request, credentials);
}
/**
* Signs an S3 request with automatic SHA256 payload calculation.
*
* @param {object} request - Request options for S3 service.
* @param {object} [credentials] - AWS credentials.
* @returns {object} Signed request object with X-Amz-Content-Sha256 header.
*/
function signS3Request(request, credentials) {
const req = Object.assign({ service: 's3' }, request);
return aws4.sign(req, credentials);
}
/**
* Creates a RequestSigner instance for custom inspection and step-by-step signing.
*
* @param {object|string} request - Request options or URL string.
* @param {object} [credentials] - AWS credentials.
* @returns {aws4.RequestSigner} RequestSigner instance.
*/
function createRequestSigner(request, credentials) {
return new aws4.RequestSigner(request, credentials);
}
module.exports = {
signRequest,
signQuery,
signWithSessionToken,
signS3Request,
createRequestSigner,
aws4,
};
import assert from 'node:assert';
import crypto from 'node:crypto';
import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);
const aws4 = require('aws4');
const {
signRequest,
signQuery,
signWithSessionToken,
signS3Request,
createRequestSigner,
} = require('../src/index.js');
const dummyCredentials = {
accessKeyId: 'mock-access-key-id',
secretAccessKey: 'mock-secret-access-key',
};
async function runContract() {
// 1. assert aws4.sign populates Authorization, X-Amz-Date, and Host headers on HTTP request options
const req1 = {
host: 'sqs.us-east-1.amazonaws.com',
path: '/?Action=ListQueues&Version=2012-11-05',
service: 'sqs',
region: 'us-east-1',
headers: {
'Date': 'Mon, 09 Sep 2024 00:00:00 GMT',
},
};
const signed1 = signRequest(req1, dummyCredentials);
assert.ok(signed1.headers.Authorization, 'Authorization header should be set');
assert.strictEqual(signed1.headers['X-Amz-Date'], '20240909T000000Z', 'X-Amz-Date should match ISO-like format');
assert.strictEqual(signed1.headers.Host, 'sqs.us-east-1.amazonaws.com', 'Host header should be set');
// 2. assert Authorization header follows AWS4-HMAC-SHA256 format containing Credential, SignedHeaders, and Signature
const authHeader = signed1.headers.Authorization;
assert.ok(
authHeader.startsWith('AWS4-HMAC-SHA256 Credential=mock-access-key-id/20240909/us-east-1/sqs/aws4_request'),
'Authorization must start with AWS4-HMAC-SHA256 and expected Credential scope'
);
assert.ok(authHeader.includes('SignedHeaders='), 'Authorization must contain SignedHeaders');
assert.ok(authHeader.includes('Signature='), 'Authorization must contain Signature');
const sigMatch = authHeader.match(/Signature=([a-f0-9]{64})/);
assert.ok(sigMatch && sigMatch[1].length === 64, 'Signature must be a 64-character hexadecimal string');
// 3. assert aws4.sign sets Content-Type and Content-Length headers for POST requests with body content
const postReq = {
host: 'dynamodb.us-east-1.amazonaws.com',
path: '/',
method: 'POST',
body: '{"TableName":"TestTable"}',
};
const signedPost = signRequest(postReq, dummyCredentials);
assert.strictEqual(
signedPost.headers['Content-Type'],
'application/x-www-form-urlencoded; charset=utf-8',
'Default Content-Type should be set for POST requests with body'
);
assert.strictEqual(
signedPost.headers['Content-Length'],
25,
'Content-Length must match byte length of payload'
);
// 4. assert aws4.sign adds X-Amz-Security-Token header and includes it in signed headers when sessionToken is provided
const stsCredentials = {
...dummyCredentials,
sessionToken: 'mock-session-token',
};
const stsReq = {
host: 'sqs.us-east-1.amazonaws.com',
path: '/',
};
const signedSts = signWithSessionToken(stsReq, stsCredentials);
assert.strictEqual(
signedSts.headers['X-Amz-Security-Token'],
'mock-session-token',
'X-Amz-Security-Token header should match session token'
);
assert.ok(
signedSts.headers.Authorization.toLowerCase().includes('x-amz-security-token'),
'Authorization SignedHeaders must include x-amz-security-token'
);
// 5. assert aws4.sign computes SHA256 payload hash and sets X-Amz-Content-Sha256 header for S3 service requests
const s3Payload = 'Sample payload for S3 upload';
const expectedS3Hash = crypto.createHash('sha256').update(s3Payload).digest('hex');
const s3Req = {
host: 'example-bucket.s3.amazonaws.com',
path: '/data.txt',
method: 'PUT',
body: s3Payload,
};
const signedS3 = signS3Request(s3Req, dummyCredentials);
assert.strictEqual(
signedS3.headers['X-Amz-Content-Sha256'],
expectedS3Hash,
'X-Amz-Content-Sha256 header must match SHA256 of the body'
);
// 6. assert aws4.sign with signQuery option embeds SigV4 parameters into query string without Authorization header
const queryReq = {
host: 'example-bucket.s3.amazonaws.com',
path: '/data.txt',
service: 's3',
region: 'us-east-1',
};
const signedQuery = signQuery(queryReq, dummyCredentials);
assert.strictEqual(signedQuery.headers.Authorization, undefined, 'Authorization header must not be set when signQuery is true');
assert.ok(signedQuery.path.includes('X-Amz-Algorithm=AWS4-HMAC-SHA256'), 'Path must contain X-Amz-Algorithm query param');
assert.ok(signedQuery.path.includes('X-Amz-Credential='), 'Path must contain X-Amz-Credential query param');
assert.ok(signedQuery.path.includes('X-Amz-Date='), 'Path must contain X-Amz-Date query param');
assert.ok(signedQuery.path.includes('X-Amz-SignedHeaders='), 'Path must contain X-Amz-SignedHeaders query param');
assert.ok(signedQuery.path.includes('X-Amz-Signature='), 'Path must contain X-Amz-Signature query param');
// 7. assert aws4.RequestSigner resolves service name and AWS region automatically from amazonaws.com hostnames
const signer = createRequestSigner({
host: 'dynamodb.eu-central-1.amazonaws.com',
path: '/',
}, dummyCredentials);
assert.strictEqual(signer.service, 'dynamodb', 'Service should be inferred as dynamodb from host');
assert.strictEqual(signer.region, 'eu-central-1', 'Region should be inferred as eu-central-1 from host');
// 8. assert aws4.RequestSigner exposes canonicalString, stringToSign, and signature generation methods
assert.strictEqual(typeof signer.canonicalString, 'function', 'canonicalString method should exist');
assert.strictEqual(typeof signer.stringToSign, 'function', 'stringToSign method should exist');
assert.strictEqual(typeof signer.signature, 'function', 'signature method should exist');
assert.strictEqual(typeof signer.authHeader, 'function', 'authHeader method should exist');
const canonical = signer.canonicalString();
assert.ok(canonical.startsWith('GET\n/'), 'Canonical request string should start with method and path');
const stringToSign = signer.stringToSign();
assert.ok(stringToSign.startsWith('AWS4-HMAC-SHA256\n'), 'String to sign must start with AWS4-HMAC-SHA256');
const signatureHex = signer.signature();
assert.strictEqual(typeof signatureHex, 'string');
assert.strictEqual(signatureHex.length, 64, 'Signature must be 64 characters hex');
console.log('Contract tests passed successfully.');
}
runContract().catch((err) => {
console.error('Contract test failed:', err);
process.exit(1);
});
Seeder de origen
anónimo