将 AWS KMS ECDSA_SHA_256 签名从 DER 编码的 ANS.1 格式转换为 JWT base64url 编码的 R || NodeJS/Javascript 中的 S 格式
Posted
技术标签:
【中文标题】将 AWS KMS ECDSA_SHA_256 签名从 DER 编码的 ANS.1 格式转换为 JWT base64url 编码的 R || NodeJS/Javascript 中的 S 格式【英文标题】:Convert AWS KMS ECDSA_SHA_256 Signature from DER encoded ANS.1 format to JWT base64url encoded R || S format in NodeJS/Javascript 【发布时间】:2021-12-05 17:14:30 【问题描述】:我正在尝试使用 AWS KMS 客户托管密钥在 NodeJS 中使用 ES256 算法创建 JWT 签名。
使用带有加密签名算法 ECDSA_SHA_256 的 AWS KMS 创建的签名不被 JWT 接受 R || S 格式。根据 AWS 文档,签名将采用 DER 编码的 ANS X9.62–2005 格式 (https://docs.aws.amazon.com/kms/latest/APIReference/API_Sign.html#API_Sign_ResponseSyntax)。
我尝试使用带有 ans1js(https://www.npmjs.com/package/asn1js) 的 NodeJS 中的以下代码将 AWS KMS 签名转换为 JWT R||S 格式,但是 R 和 S 的长度并不一致,为 32 + 32,而是最多变化 33时间。
function toArrayBuffer(buffer)
const ab = new ArrayBuffer(buffer.length);
const view = new Uint8Array(ab);
for (let i = 0; i < buffer.length; ++i)
view[i] = buffer[i];
return ab;
//call this with your signature buffer
function parseBERSignature(sig)
const result = asn1js.fromBER(toArrayBuffer(sig));
const part1 = result.valueBlock.value[0];
const part2 = result.valueBlock.value[1];
let r = Buffer.from(part1.valueBlock.valueHex);
let s = Buffer.from(part2.valueBlock.valueHex);
console.log("R value", r);
console.log("S value", s);
console.log("R value", r.toString('base64'));
console.log("S value", s.toString('base64'));
console.log("R length", r.length);
console.log("S length", s.length);
return base64url.fromBase64(Buffer.concat([r, s]).toString('base64'));
创建签名的完整代码:
const base64url = require('base64url')
const AWS = require('aws-sdk');
const kms = new AWS.KMS();
const asn1js = require('asn1js')
const keyid = "9001e08c-b7bc-4f53-9eca-ec034904cdd5";
const header =
"typ": "JWT",
"alg": "ES256",
"kid": keyid
const payload =
"sub": "name",
"status": "valid",
"aud": "name"
exports.handler = async function (event, context, callback)
console.log("Hello, new World");
payload.iat = Math.floor(Date.now() / 1000);
console.log("header", header);
console.log("payload", payload);
const jwtHeader = base64url(JSON.stringify(header));
const jwtPayload = base64url(JSON.stringify(payload));
console.log("jwtHeader", jwtHeader);
console.log("jwtPayload", jwtPayload);
const message = Buffer.from(jwtHeader + "." + jwtPayload);
const messageDigest = createHash(message);
let kmsResponse = await kms.sign(
Message: message,
KeyId: keyid,
SigningAlgorithm: 'ECDSA_SHA_256',
MessageType: 'RAW'
).promise();
console.log("Signature RAW", kmsResponse.Signature);
console.log("Signature String", kmsResponse.Signature.toString());
console.log("Signature base64", kmsResponse.Signature.toString('base64'));
let response = parseBERSignature(kmsResponse.Signature);
console.log("response", response);
return jwtHeader + "." + jwtPayload + "." + response;
任何将 DER 编码的 ANS 格式转换为 R 的 NodeJs javascript 实现 || S格式base64url编码?
【问题讨论】:
【参考方案1】:任何将 DER 编码的 ANS 格式转换为 R 的 NodeJs Javascript 实现 || S格式base64url编码?
是的,ecdsa-sig-formatter 将帮助您在格式之间来回转换签名。
【讨论】:
以上是关于将 AWS KMS ECDSA_SHA_256 签名从 DER 编码的 ANS.1 格式转换为 JWT base64url 编码的 R || NodeJS/Javascript 中的 S 格式的主要内容,如果未能解决你的问题,请参考以下文章
java AWS中的AWS KMS decryptRequest
Amazon S3 存储桶加密 - KMS 与 AES 256
使用 Cloudformation 创建 KMS 密钥时出现消息“没有 IAM 权限来处理 AWS::KMS::Key 资源上的标签”