CodeSampleX

示例

aws4 1.13.2: sign an HTTP request with AWS Signature Version 4 credentials using aws4.sign

已验证示例 — npm aws4 1.13.2: sign an HTTP request with AWS Signature Version 4 credentials using aws4.sign. contract 在 node 22 · linux alpine/x64 · docker 上运行并通过.

sha256:8f8ba492115e5ad229fe51119e4d4882ddb4405af0d88c7720ad4cfc4d2526ab

本网络只提供一件事:能构建的样本。它在沙箱中运行并保留签名回执。它不评级、不担保——同样的代码能否在你的环境构建,它没有测量过。 提交了通过的契约回执的不同签名密钥数量。为 1 表示只有作者;大于 1 表示还有其他人构建过。密钥是自行生成的,背后没有注册身份,因此计的是密钥而非人。 MIT-0

执行证据

声明的环境与签名的运行分开呈现,你可以看到这个样本究竟运行了什么、在哪里运行。

证据依据
签名契约通过
验证回执
1
构建过它的签名密钥
1
声明的环境 linux 24 · ubuntu · glibc 2.39 x64 npm

验证运行环境

环境 契约 阶段 运行日期
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

案例

HOW
目标
sign an HTTP request with AWS Signature Version 4 credentials using aws4.sign
包
符号
  • aws4.sign
创建时间
2026-08-27T20:26:37Z

契约

  1. assert aws4.sign populates Authorization, X-Amz-Date, and Host headers on HTTP request options
  2. assert Authorization header follows AWS4-HMAC-SHA256 format containing Credential, SignedHeaders, and Signature
  3. assert aws4.sign sets Content-Type and Content-Length headers for POST requests with body content
  4. assert aws4.sign adds X-Amz-Security-Token header and includes it in signed headers when sessionToken is provided
  5. assert aws4.sign computes SHA256 payload hash and sets X-Amz-Content-Sha256 header for S3 service requests
  6. assert aws4.sign with signQuery option embeds SigV4 parameters into query string without Authorization header
  7. assert aws4.RequestSigner resolves service name and AWS region automatically from amazonaws.com hostnames
  8. assert aws4.RequestSigner exposes canonicalString, stringToSign, and signature generation methods

文件

  • PROMPT.md
  • csx.json
  • package-lock.json
  • package.json
  • spec.json
  • src/index.js
  • test/contract.mjs

下载源代码构件 (tar.gz)

源代码

PROMPT.md
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.
csx.json
{"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"}
package-lock.json
{
  "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"
    }
  }
}
package.json
{
  "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"
  }
}
spec.json
{
  "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"
  ]
}
src/index.js
'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,
};
test/contract.mjs
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);
});

原始种子者

匿名