|
1 | 1 | import {
|
| 2 | + isPublicKeyAlgorithm, |
2 | 3 | KasPublicKeyAlgorithm,
|
3 | 4 | KasPublicKeyInfo,
|
4 | 5 | noteInvalidPublicKey,
|
@@ -74,6 +75,31 @@ export async function fetchKeyAccessServers(
|
74 | 75 | return new OriginAllowList(serverUrls, false);
|
75 | 76 | }
|
76 | 77 |
|
| 78 | +interface PlatformBaseKey { |
| 79 | + kas_id?: string; |
| 80 | + kas_uri: string; |
| 81 | + public_key: { |
| 82 | + algorithm: KasPublicKeyAlgorithm; |
| 83 | + kid: string; |
| 84 | + pem: string; |
| 85 | + }; |
| 86 | +} |
| 87 | + |
| 88 | +function isBaseKey(baseKey?: unknown): baseKey is PlatformBaseKey { |
| 89 | + if (!baseKey) { |
| 90 | + return false; |
| 91 | + } |
| 92 | + const bk = baseKey as PlatformBaseKey; |
| 93 | + return ( |
| 94 | + !!bk.kas_uri && |
| 95 | + !!bk.public_key && |
| 96 | + typeof bk.public_key === 'object' && |
| 97 | + !!bk.public_key.pem && |
| 98 | + !!bk.public_key.algorithm && |
| 99 | + isPublicKeyAlgorithm(bk.public_key.algorithm) |
| 100 | + ); |
| 101 | +} |
| 102 | + |
77 | 103 | export async function fetchKasPubKey(
|
78 | 104 | kasEndpoint: string,
|
79 | 105 | algorithm?: KasPublicKeyAlgorithm
|
@@ -105,3 +131,45 @@ export async function fetchKasPubKey(
|
105 | 131 | throw new NetworkError(`[${platformUrl}] [PublicKey] ${extractRpcErrorMessage(e)}`);
|
106 | 132 | }
|
107 | 133 | }
|
| 134 | + |
| 135 | +/** |
| 136 | + * Fetch the base public key from WellKnownConfiguration of the platform. |
| 137 | + * @param kasEndpoint The KAS endpoint URL. |
| 138 | + * @throws {ConfigurationError} If the KAS endpoint is not defined. |
| 139 | + * @throws {NetworkError} If there is an error fetching the public key from the KAS endpoint. |
| 140 | + * @returns The base public key information for the KAS endpoint. |
| 141 | + */ |
| 142 | +export async function fetchKasBasePubKey(kasEndpoint: string): Promise<KasPublicKeyInfo> { |
| 143 | + if (!kasEndpoint) { |
| 144 | + throw new ConfigurationError('KAS definition not found'); |
| 145 | + } |
| 146 | + validateSecureUrl(kasEndpoint); |
| 147 | + |
| 148 | + const platformUrl = getPlatformUrlFromKasEndpoint(kasEndpoint); |
| 149 | + const platform = new PlatformClient({ |
| 150 | + platformUrl, |
| 151 | + }); |
| 152 | + try { |
| 153 | + const { configuration } = await platform.v1.wellknown.getWellKnownConfiguration({}); |
| 154 | + const baseKey = configuration?.base_key as unknown as PlatformBaseKey; |
| 155 | + if (!isBaseKey(baseKey)) { |
| 156 | + throw new NetworkError( |
| 157 | + `Invalid Platform Configuration: [${kasEndpoint}] is missing BaseKey in WellKnownConfiguration` |
| 158 | + ); |
| 159 | + } |
| 160 | + |
| 161 | + const result: KasPublicKeyInfo = { |
| 162 | + key: noteInvalidPublicKey( |
| 163 | + new URL(baseKey.kas_uri), |
| 164 | + pemToCryptoPublicKey(baseKey.public_key.pem) |
| 165 | + ), |
| 166 | + publicKey: baseKey.public_key.pem, |
| 167 | + url: baseKey.kas_uri, |
| 168 | + algorithm: baseKey.public_key.algorithm, |
| 169 | + kid: baseKey.public_key.kid, |
| 170 | + }; |
| 171 | + return result; |
| 172 | + } catch (e) { |
| 173 | + throw new NetworkError(`[${platformUrl}] [PublicKey] ${extractRpcErrorMessage(e)}`); |
| 174 | + } |
| 175 | +} |
0 commit comments