@originator-profile/securing-mechanism 0.6.1 → 0.7.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,5 @@
1
1
  # Profile JWT Securing Mechanism
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/@originator-profile/securing-mechanism)](https://www.npmjs.com/package/@originator-profile/securing-mechanism) [![jsDocs.io](https://img.shields.io/badge/jsDocs.io-reference-blue)](https://www.jsdocs.io/package/@originator-profile/securing-mechanism)
4
+
3
5
  VC の Securing 処理をするためのパッケージです。
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { OpVc, Jwk } from '@originator-profile/model';
2
2
  import { JWTInvalid, JOSEError } from 'jose/errors';
3
- import { JWTPayload, ProtectedHeaderParameters } from 'jose';
3
+ import { JWTPayload, ProtectedHeaderParameters, CryptoKey, KeyObject } from 'jose';
4
4
  import { Keys } from '@originator-profile/cryptography';
5
5
  import { ZodType } from 'zod';
6
6
 
@@ -114,6 +114,28 @@ type JwtVcDecoder<T extends OpVc> = ReturnType<typeof JwtVcDecoder<T>>;
114
114
  declare function toUnverifiedJwtVc<T extends OpVc>(payload: JWTPayload, protectedHeader: ProtectedHeaderParameters, jwt: string): UnverifiedJwtVc<T>;
115
115
  declare function toVerifiedJwtVc<T extends OpVc>(payload: JWTPayload, protectedHeader: ProtectedHeaderParameters, jwt: string, key: Jwk): VerifiedJwtVc<T>;
116
116
 
117
+ /**
118
+ * 鍵材料を外部に渡さない不透明な署名者
119
+ *
120
+ * HSM・セキュアエレメント・クラウドKMS(AWS KMS, Google Cloud KMS, Azure Key Vault等)・
121
+ * WebAuthn/FIDO2など、秘密鍵をハードウェア境界外に取り出せない署名環境向けの注入口。
122
+ */
123
+ type JwtSigner = {
124
+ /** JWS alg */
125
+ alg: string;
126
+ /** JWS kid (鍵材料を持たないためサムプリントによるフォールバック計算ができない) */
127
+ kid: string;
128
+ /**
129
+ * signingInput (base64url(header) + "." + base64url(payload) の ASCII バイト列) に対する
130
+ * 生の署名バイト列 (JOSE 形式。例えば ES256 なら r||s の固定長結合) を返す。
131
+ */
132
+ sign: (signingInput: Uint8Array) => Promise<Uint8Array>;
133
+ };
134
+ /** ソフトウェア鍵として直接扱える鍵材料 */
135
+ type KeyMaterial = Jwk | CryptoKey | KeyObject;
136
+ /** signer が JwtSigner (不透明な署名者) かどうかを判定する */
137
+ declare function isJwtSigner(signer: KeyMaterial | JwtSigner): signer is JwtSigner;
138
+
117
139
  type SignableVc = {
118
140
  issuer: string;
119
141
  credentialSubject: {
@@ -123,11 +145,12 @@ type SignableVc = {
123
145
  /**
124
146
  * VC への署名
125
147
  * @param vc VC オブジェクト
126
- * @param privateKey プライベートキー
148
+ * @param signer プライベートキー (Jwk/CryptoKey/KeyObject)、または HSM・KMS・WebAuthn等の外部署名者 (JwtSigner)
127
149
  * @return JWT でエンコードされた VC
128
150
  */
129
- declare function signJwtVc<T extends SignableVc>(vc: T, privateKey: Jwk, options: {
151
+ declare function signJwtVc<T extends SignableVc>(vc: T, signer: KeyMaterial | JwtSigner, options: {
130
152
  alg?: string;
153
+ kid?: string;
131
154
  issuedAt: Date;
132
155
  expiredAt: Date;
133
156
  }): Promise<string>;
@@ -147,5 +170,5 @@ type VcValidator<V extends UnverifiedVc> = ReturnType<typeof VcValidator<V>>;
147
170
  declare function JwtVcVerifier<T extends OpVc>(keys: Keys, issuer: string | string[], validator?: VcValidator<VerifiedJwtVc<T>>): (jwt: string) => Promise<JwtVcVerificationResult<T>>;
148
171
  type JwtVcVerifier<T extends OpVc> = ReturnType<typeof JwtVcVerifier<T>>;
149
172
 
150
- export { JwtVcDecoder, JwtVcVerifier, SchemaValidationError, VcDecodeFailed, VcValidateFailed, VcValidator, VcVerifyFailed, signJwtVc, toUnverifiedJwtVc, toVerifiedJwtVc };
151
- export type { JwtVcDecodingFailure, JwtVcDecodingResult, JwtVcValidationResult, JwtVcVerificationFailure, JwtVcVerificationResult, SchemaIssue, UndecodedJwtVc, UndecodedVc, UnverifiedJwtVc, UnverifiedVc, VcDecodingFailure, VcDecodingResult, VcValidationFailure, VcValidationResult, VcVerificationFailure, VcVerificationResult, VerifiedJwtVc, VerifiedVc };
173
+ export { JwtVcDecoder, JwtVcVerifier, SchemaValidationError, VcDecodeFailed, VcValidateFailed, VcValidator, VcVerifyFailed, isJwtSigner, signJwtVc, toUnverifiedJwtVc, toVerifiedJwtVc };
174
+ export type { JwtSigner, JwtVcDecodingFailure, JwtVcDecodingResult, JwtVcValidationResult, JwtVcVerificationFailure, JwtVcVerificationResult, KeyMaterial, SchemaIssue, UndecodedJwtVc, UndecodedVc, UnverifiedJwtVc, UnverifiedVc, VcDecodingFailure, VcDecodingResult, VcValidationFailure, VcValidationResult, VcVerificationFailure, VcVerificationResult, VerifiedJwtVc, VerifiedVc };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { decodeJwt, decodeProtectedHeader, importJWK, SignJWT, jwtVerify, exportJWK } from 'jose';
1
+ import { decodeJwt, decodeProtectedHeader, base64url, importJWK, SignJWT, exportJWK, jwtVerify } from 'jose';
2
2
  import { createThumbprint } from '@originator-profile/cryptography';
3
3
  import { JOSEError } from 'jose/errors';
4
4
 
@@ -108,18 +108,61 @@ function JwtVcDecoder() {
108
108
  return decode;
109
109
  }
110
110
 
111
- async function signJwtVc(vc, privateKey, options) {
112
- const payload = vc;
113
- const { alg = "ES256", issuedAt, expiredAt } = options;
114
- const header = {
115
- alg,
116
- kid: privateKey.kid ?? await createThumbprint(privateKey, alg),
117
- typ: "vc+jwt",
118
- cty: "vc"
119
- };
120
- const privateKeyImported = await importJWK(privateKey, alg);
121
- const jwt = await new SignJWT(payload).setProtectedHeader(header).setIssuer(vc.issuer).setSubject(vc.credentialSubject.id).setIssuedAt(getUnixTime(issuedAt)).setExpirationTime(getUnixTime(expiredAt)).sign(privateKeyImported);
122
- return jwt;
111
+ function isJwtSigner(signer) {
112
+ return !("kty" in signer) && "sign" in signer && typeof signer.sign === "function";
113
+ }
114
+
115
+ function isJwk(keyMaterial) {
116
+ return "kty" in keyMaterial;
117
+ }
118
+ async function resolveKid(keyMaterial) {
119
+ if (isJwk(keyMaterial)) {
120
+ return keyMaterial.kid ?? await createThumbprint(keyMaterial);
121
+ }
122
+ try {
123
+ const jwk = await exportJWK(keyMaterial);
124
+ return await createThumbprint(jwk);
125
+ } catch (e) {
126
+ throw new Error(
127
+ "Could not derive kid from the key (it may be non-extractable). Specify options.kid explicitly.",
128
+ { cause: e }
129
+ );
130
+ }
131
+ }
132
+ async function resolveAlgAndKid(signer, options) {
133
+ if (isJwtSigner(signer)) {
134
+ if (options.alg !== void 0 && options.alg !== signer.alg) {
135
+ throw new Error(
136
+ `options.alg ("${options.alg}") must match signer.alg ("${signer.alg}").`
137
+ );
138
+ }
139
+ return { alg: signer.alg, kid: options.kid ?? signer.kid };
140
+ }
141
+ const alg = options.alg ?? "ES256";
142
+ return { alg, kid: options.kid ?? await resolveKid(signer) };
143
+ }
144
+ async function signJwtVc(vc, signer, options) {
145
+ const { issuedAt, expiredAt } = options;
146
+ const { alg, kid } = await resolveAlgAndKid(signer, options);
147
+ const header = { alg, kid, typ: "vc+jwt", cty: "vc" };
148
+ if (isJwtSigner(signer)) {
149
+ const claims = {
150
+ ...vc,
151
+ iss: vc.issuer,
152
+ sub: vc.credentialSubject.id,
153
+ iat: getUnixTime(issuedAt),
154
+ exp: getUnixTime(expiredAt)
155
+ };
156
+ const encodedHeader = base64url.encode(JSON.stringify(header));
157
+ const encodedPayload = base64url.encode(JSON.stringify(claims));
158
+ const signingInput = new TextEncoder().encode(
159
+ `${encodedHeader}.${encodedPayload}`
160
+ );
161
+ const signature = await signer.sign(signingInput);
162
+ return `${encodedHeader}.${encodedPayload}.${base64url.encode(signature)}`;
163
+ }
164
+ const key = isJwk(signer) ? await importJWK(signer, alg) : signer;
165
+ return await new SignJWT(vc).setProtectedHeader(header).setIssuer(vc.issuer).setSubject(vc.credentialSubject.id).setIssuedAt(getUnixTime(issuedAt)).setExpirationTime(getUnixTime(expiredAt)).sign(key);
123
166
  }
124
167
 
125
168
  function JwtVcVerifier(keys, issuer, validator) {
@@ -174,4 +217,4 @@ function VcValidator(schema) {
174
217
  return validate;
175
218
  }
176
219
 
177
- export { JwtVcDecoder, JwtVcVerifier, SchemaValidationError, VcDecodeFailed, VcValidateFailed, VcValidator, VcVerifyFailed, signJwtVc, toUnverifiedJwtVc, toVerifiedJwtVc };
220
+ export { JwtVcDecoder, JwtVcVerifier, SchemaValidationError, VcDecodeFailed, VcValidateFailed, VcValidator, VcVerifyFailed, isJwtSigner, signJwtVc, toUnverifiedJwtVc, toVerifiedJwtVc };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@originator-profile/securing-mechanism",
3
- "version": "0.6.1",
3
+ "version": "0.7.0-beta.2",
4
4
  "license": "Apache-2.0",
5
5
  "homepage": "https://docs.originator-profile.org",
6
6
  "repository": {
@@ -25,22 +25,21 @@
25
25
  "dependencies": {
26
26
  "jose": "^6.2.2",
27
27
  "zod": "^4.3.6",
28
- "@originator-profile/cryptography": "0.6.1",
29
- "@originator-profile/model": "0.6.1"
28
+ "@originator-profile/cryptography": "0.7.0-beta.2",
29
+ "@originator-profile/model": "0.7.0-beta.2"
30
30
  },
31
31
  "devDependencies": {
32
32
  "date-fns": "4.1.0",
33
- "eslint": "10.2.0",
33
+ "oxlint": "^1.73.0",
34
+ "oxlint-tsgolint": "^0.24.0",
34
35
  "pkgroll": "2.27.0",
35
36
  "typescript": "6.0.2",
36
37
  "vitest": "4.1.4",
37
- "eslint-config-originator-profile": "0.6.1",
38
- "@originator-profile/tsconfig": "0.6.1"
38
+ "@originator-profile/tsconfig": "0.7.0-beta.2"
39
39
  },
40
40
  "scripts": {
41
41
  "build": "pkgroll --clean-dist",
42
42
  "test": "vitest run",
43
- "lint": "eslint --fix .",
44
- "type-check": "tsc --noEmit"
43
+ "lint": "oxlint --fix ."
45
44
  }
46
45
  }