@sphereon/ssi-sdk-ext.key-utils 0.36.1-feature.SSISDK.44.finish.dcql.1 → 0.36.1-feature.SSISDK.70.integrate.digidentity.55

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/src/functions.ts CHANGED
@@ -31,6 +31,7 @@ import * as u8a from 'uint8arrays'
31
31
  import { digestMethodParams } from './digest-methods'
32
32
  import { validateJwk } from './jwk-jcs'
33
33
  import {
34
+ DigestAlgorithm,
34
35
  ENC_KEY_ALGS,
35
36
  type IImportProvidedOrGeneratedKeyArgs,
36
37
  JwkKeyUse,
@@ -198,8 +199,8 @@ export const toBase64url = (input: string): string => toString(fromString(input)
198
199
  * Calculate the JWK thumbprint
199
200
  * @param args
200
201
  */
201
- export const calculateJwkThumbprint = (args: { jwk: JWK; digestAlgorithm?: 'sha256' | 'sha512' }): string => {
202
- const { digestAlgorithm = 'sha256' } = args
202
+ export const calculateJwkThumbprint = (args: { jwk: JWK; digestAlgorithm?: DigestAlgorithm }): string => {
203
+ const digestAlgorithm = normalizeHashAlgorithm(args.digestAlgorithm ?? 'SHA-256')
203
204
  const jwk = sanitizedJwk(args.jwk)
204
205
  let components
205
206
  switch (jwk.kty) {
@@ -227,10 +228,7 @@ export const calculateJwkThumbprint = (args: { jwk: JWK; digestAlgorithm?: 'sha2
227
228
  throw new Error('"kty" (Key Type) Parameter missing or unsupported')
228
229
  }
229
230
  const data = JSON.stringify(components)
230
-
231
- return digestAlgorithm === 'sha512'
232
- ? digestMethodParams('SHA-512').digestMethod(data, 'base64url')
233
- : digestMethodParams('SHA-256').digestMethod(data, 'base64url')
231
+ return digestMethodParams(digestAlgorithm).digestMethod(data, 'base64url')
234
232
  }
235
233
 
236
234
  export const toJwkFromKey = (
@@ -791,11 +789,49 @@ export const hexStringFromUint8Array = (value: Uint8Array): string => toString(v
791
789
 
792
790
  export const signatureAlgorithmFromKey = async (args: SignatureAlgorithmFromKeyArgs): Promise<JoseSignatureAlgorithm> => {
793
791
  const { key } = args
794
- return signatureAlgorithmFromKeyType({ type: key.type })
792
+ return signatureAlgorithmFromKeyType({ type: key.type, algorithms: key.meta?.algorithms })
793
+ }
794
+
795
+ export function signatureAlgorithmToJoseAlgorithm(alg: string): JoseSignatureAlgorithm {
796
+ switch (alg) {
797
+ case 'RSA_SHA256':
798
+ return JoseSignatureAlgorithm.RS256
799
+ case 'RSA_SHA384':
800
+ return JoseSignatureAlgorithm.RS384
801
+ case 'RSA_SHA512':
802
+ return JoseSignatureAlgorithm.RS512
803
+ case 'RSA_SSA_PSS_SHA256_MGF1':
804
+ return JoseSignatureAlgorithm.PS256
805
+ case 'RSA_SSA_PSS_SHA384_MGF1':
806
+ return JoseSignatureAlgorithm.PS384
807
+ case 'RSA_SSA_PSS_SHA512_MGF1':
808
+ return JoseSignatureAlgorithm.PS512
809
+ case 'ECDSA_SHA256':
810
+ return JoseSignatureAlgorithm.ES256
811
+ case 'ECDSA_SHA384':
812
+ return JoseSignatureAlgorithm.ES384
813
+ case 'ECDSA_SHA512':
814
+ return JoseSignatureAlgorithm.ES512
815
+ case 'ES256K':
816
+ return JoseSignatureAlgorithm.ES256K
817
+ case 'ED25519':
818
+ case 'EdDSA':
819
+ return JoseSignatureAlgorithm.EdDSA
820
+ default:
821
+ // If already in JOSE format, return as-is
822
+ return alg as JoseSignatureAlgorithm
823
+ }
795
824
  }
796
825
 
797
826
  export const signatureAlgorithmFromKeyType = (args: SignatureAlgorithmFromKeyTypeArgs): JoseSignatureAlgorithm => {
798
- const { type } = args
827
+ const { type, algorithms } = args
828
+
829
+ // If algorithms metadata is provided, use the first one
830
+ if (algorithms && algorithms.length > 0) {
831
+ return signatureAlgorithmToJoseAlgorithm(algorithms[0])
832
+ }
833
+
834
+ // Fallback to type-based defaults
799
835
  switch (type) {
800
836
  case 'Ed25519':
801
837
  case 'X25519':
@@ -809,7 +845,7 @@ export const signatureAlgorithmFromKeyType = (args: SignatureAlgorithmFromKeyTyp
809
845
  case 'Secp256k1':
810
846
  return JoseSignatureAlgorithm.ES256K
811
847
  case 'RSA':
812
- return JoseSignatureAlgorithm.PS256
848
+ return JoseSignatureAlgorithm.RS256 // Default to RS256 instead of PS256
813
849
  default:
814
850
  throw new Error(`Key type '${type}' not supported`)
815
851
  }
@@ -1122,3 +1158,73 @@ export function toPkcs1FromHex(publicKeyHex: string) {
1122
1158
  const pkcs1 = toPkcs1(fromString(publicKeyHex, 'hex'))
1123
1159
  return toString(pkcs1, 'hex')
1124
1160
  }
1161
+
1162
+ export function joseAlgorithmToDigest(alg: string): DigestAlgorithm {
1163
+ switch (alg.toUpperCase().replace('-', '')) {
1164
+ case 'RS256':
1165
+ case 'ES256':
1166
+ case 'ES256K':
1167
+ case 'PS256':
1168
+ case 'HS256':
1169
+ return 'SHA-256'
1170
+ case 'RS384':
1171
+ case 'ES384':
1172
+ case 'PS384':
1173
+ case 'HS384':
1174
+ return 'SHA-384'
1175
+ case 'RS512':
1176
+ case 'ES512':
1177
+ case 'PS512':
1178
+ case 'HS512':
1179
+ return 'SHA-512'
1180
+ case 'EdDSA':
1181
+ return 'SHA-512'
1182
+ default:
1183
+ return 'SHA-256'
1184
+ }
1185
+ }
1186
+
1187
+ export function isHash(input: string): boolean {
1188
+ const length = input.length
1189
+ // SHA-256: 64 hex chars, SHA-384: 96 hex chars, SHA-512: 128 hex chars
1190
+ if (length !== 64 && length !== 96 && length !== 128) {
1191
+ return false
1192
+ }
1193
+ return input.match(/^([0-9A-Fa-f])+$/g) !== null
1194
+ }
1195
+
1196
+ export function isHashString(input: Uint8Array): boolean {
1197
+ const length = input.length
1198
+ // SHA-256: 32 bytes, SHA-384: 48 bytes, SHA-512: 64 bytes
1199
+ if (length !== 32 && length !== 48 && length !== 64) {
1200
+ return false
1201
+ }
1202
+ for (let i = 0; i < length; i++) {
1203
+ const byte = input[i]
1204
+ if (byte === undefined) {
1205
+ return false
1206
+ }
1207
+ // 0-9: 48-57, A-F: 65-70, a-f: 97-102
1208
+ if (!((byte >= 48 && byte <= 57) || (byte >= 65 && byte <= 70) || (byte >= 97 && byte <= 102))) {
1209
+ return false
1210
+ }
1211
+ }
1212
+ return true
1213
+ }
1214
+
1215
+ export type HashAlgorithm = 'SHA-256' | 'sha256' | 'SHA-384' | 'sha384' | 'SHA-512' | 'sha512'
1216
+
1217
+ export function normalizeHashAlgorithm(alg?: HashAlgorithm): 'SHA-256' | 'SHA-384' | 'SHA-512' {
1218
+ if (!alg) {
1219
+ return 'SHA-256'
1220
+ }
1221
+ const upper = alg.toUpperCase()
1222
+ if (upper.includes('256')) return 'SHA-256'
1223
+ if (upper.includes('384')) return 'SHA-384'
1224
+ if (upper.includes('512')) return 'SHA-512'
1225
+ throw new Error(`Invalid hash algorithm: ${alg}`)
1226
+ }
1227
+
1228
+ export function isSameHash(left: HashAlgorithm, right: HashAlgorithm): boolean {
1229
+ return normalizeHashAlgorithm(left) === normalizeHashAlgorithm(right)
1230
+ }
@@ -21,6 +21,8 @@ export const ENC_KEY_ALGS = ['X25519', 'ECDH_ES_A256KW', 'RSA_OAEP_256']
21
21
 
22
22
  export type KeyVisibility = 'public' | 'private'
23
23
 
24
+ export type DigestAlgorithm = 'SHA-256' | 'sha256' | 'SHA-384' | 'sha384' | 'SHA-512' | 'sha512'
25
+
24
26
  export interface X509Opts {
25
27
  cn?: string // The certificate Common Name. Will be used as the KID for the private key. Uses alias if not provided.
26
28
  privateKeyPEM?: string // Optional as you also need to provide it in hex format, but advisable to use it
@@ -53,6 +55,7 @@ export type SignatureAlgorithmFromKeyArgs = {
53
55
 
54
56
  export type SignatureAlgorithmFromKeyTypeArgs = {
55
57
  type: TKeyType
58
+ algorithms?: string[]
56
59
  }
57
60
 
58
61
  export type KeyTypeFromCryptographicSuiteArgs = {