@tinycloud/share-sdk 1.4.1-beta.1 → 1.4.1-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/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- export { D as DEFAULT_MAX_CONTENT_BLOB_BYTES, a as DEFAULT_MAX_SEALED_BLOB_BYTES, S as SHARE_RESULT_VERSION, b as ShareErrorCode, c as ShareErrorInfo, d as ShareFetchOptions, e as ShareInspection, f as ShareMetadata, g as ShareNodeTrust, h as SharePolicyAuthority, i as SharePolicyChallenge, j as SharePolicyDelegationLink, k as SharePolicyEvidence, l as SharePolicySession, m as SharePresentationMaterial, n as ShareReceiveAuthorizationRequired, o as ShareReceiveError, p as ShareReceiveOutcome, q as ShareReceiveResult, r as ShareRecipientClient, s as ShareRecipientClientOptions, t as createAddressedAuthorization, u as inspectShare, v as receiveShare, w as toShareErrorInfo } from './web-recipient-entry-Cy1fXl_5.cjs';
1
+ export { D as DEFAULT_MAX_CONTENT_BLOB_BYTES, a as DEFAULT_MAX_SEALED_BLOB_BYTES, S as SHARE_RESULT_VERSION, b as ShareErrorCode, c as ShareErrorInfo, d as ShareFetchOptions, e as ShareInspection, f as ShareMetadata, g as ShareNodeTrust, h as SharePolicyAuthority, i as SharePolicyChallenge, j as SharePolicyDelegationLink, k as SharePolicyEvidence, l as SharePolicySession, m as SharePresentationMaterial, n as ShareReceiveAuthorizationRequired, o as ShareReceiveError, p as ShareReceiveOutcome, q as ShareReceiveResult, r as ShareRecipientClient, s as ShareRecipientClientOptions, t as createAddressedAuthorization, u as inspectShare, v as receiveShare, w as toShareErrorInfo } from './web-recipient-entry-Bn3yRB7g.cjs';
2
2
  export { C as CreateOwnerDelegationParams, h as DEFAULT_SHARE_LIFETIME_MS, D as DelegatedShareKey, M as MAX_CONTENT_BYTES, i as OWNER_SHARE_REGISTRATION_DOMAIN, j as OwnerDelegationPermission, g as OwnerDelegationReceipt, O as OwnerShareAction, k as OwnerShareDecryption, a as OwnerShareMatcher, l as OwnerSharePolicyRegistration, b as OwnerSharePolicyRegistrationReceipt, m as OwnerSharePolicyV2, c as PublishedShare, P as PublishedShareDeliveryMaterial, n as PublishedShareMetadata, R as RegisterOwnerSharePolicyParams, o as SHARE_CONTENT_LIMIT, p as SHARE_PUBLISH_RESULT_VERSION, f as SharePublishError, q as SharePublishErrorCode, e as SharePublishOptions, d as SharePublishTarget, S as SignedDelegation, r as canonicalOwnerSharePolicy, s as computeOwnerShareRegistrationCid, t as createDelegatedShareKey, u as createPolicyEnforcementDelegation, v as redactPublishedShare, w as restoreDelegatedShareKey, x as validateOwnerSharePolicyRegistration, y as validateOwnerSharePolicyRegistrationBytes } from './owner-policy-aPmXIR3e.cjs';
3
3
  import { ShareEnvelopeV2, ArtifactPin, UnsignedShareEnvelopeV3, ShareEnvelopeV3 } from '@tinycloud/share-envelope';
4
4
  export { CheckBearerDelegationOptions, DelegationCheckResult, canonicalize, checkBearerDelegation, fromBase64Url, requiredResourceUri, resourceUriCovers, toBase64Url } from '@tinycloud/share-envelope';
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { D as DEFAULT_MAX_CONTENT_BLOB_BYTES, a as DEFAULT_MAX_SEALED_BLOB_BYTES, S as SHARE_RESULT_VERSION, b as ShareErrorCode, c as ShareErrorInfo, d as ShareFetchOptions, e as ShareInspection, f as ShareMetadata, g as ShareNodeTrust, h as SharePolicyAuthority, i as SharePolicyChallenge, j as SharePolicyDelegationLink, k as SharePolicyEvidence, l as SharePolicySession, m as SharePresentationMaterial, n as ShareReceiveAuthorizationRequired, o as ShareReceiveError, p as ShareReceiveOutcome, q as ShareReceiveResult, r as ShareRecipientClient, s as ShareRecipientClientOptions, t as createAddressedAuthorization, u as inspectShare, v as receiveShare, w as toShareErrorInfo } from './web-recipient-entry-CPntAP0H.js';
1
+ export { D as DEFAULT_MAX_CONTENT_BLOB_BYTES, a as DEFAULT_MAX_SEALED_BLOB_BYTES, S as SHARE_RESULT_VERSION, b as ShareErrorCode, c as ShareErrorInfo, d as ShareFetchOptions, e as ShareInspection, f as ShareMetadata, g as ShareNodeTrust, h as SharePolicyAuthority, i as SharePolicyChallenge, j as SharePolicyDelegationLink, k as SharePolicyEvidence, l as SharePolicySession, m as SharePresentationMaterial, n as ShareReceiveAuthorizationRequired, o as ShareReceiveError, p as ShareReceiveOutcome, q as ShareReceiveResult, r as ShareRecipientClient, s as ShareRecipientClientOptions, t as createAddressedAuthorization, u as inspectShare, v as receiveShare, w as toShareErrorInfo } from './web-recipient-entry-CTFoIH8l.js';
2
2
  export { C as CreateOwnerDelegationParams, h as DEFAULT_SHARE_LIFETIME_MS, D as DelegatedShareKey, M as MAX_CONTENT_BYTES, i as OWNER_SHARE_REGISTRATION_DOMAIN, j as OwnerDelegationPermission, g as OwnerDelegationReceipt, O as OwnerShareAction, k as OwnerShareDecryption, a as OwnerShareMatcher, l as OwnerSharePolicyRegistration, b as OwnerSharePolicyRegistrationReceipt, m as OwnerSharePolicyV2, c as PublishedShare, P as PublishedShareDeliveryMaterial, n as PublishedShareMetadata, R as RegisterOwnerSharePolicyParams, o as SHARE_CONTENT_LIMIT, p as SHARE_PUBLISH_RESULT_VERSION, f as SharePublishError, q as SharePublishErrorCode, e as SharePublishOptions, d as SharePublishTarget, S as SignedDelegation, r as canonicalOwnerSharePolicy, s as computeOwnerShareRegistrationCid, t as createDelegatedShareKey, u as createPolicyEnforcementDelegation, v as redactPublishedShare, w as restoreDelegatedShareKey, x as validateOwnerSharePolicyRegistration, y as validateOwnerSharePolicyRegistrationBytes } from './owner-policy-aPmXIR3e.js';
3
3
  import { ShareEnvelopeV2, ArtifactPin, UnsignedShareEnvelopeV3, ShareEnvelopeV3 } from '@tinycloud/share-envelope';
4
4
  export { CheckBearerDelegationOptions, DelegationCheckResult, canonicalize, checkBearerDelegation, fromBase64Url, requiredResourceUri, resourceUriCovers, toBase64Url } from '@tinycloud/share-envelope';
package/dist/index.js CHANGED
@@ -8710,41 +8710,18 @@ function bytes2(value, label) {
8710
8710
  if (decoded.length !== 64 || toBase64Url(decoded) !== value) throw new Error(`${label} is invalid`);
8711
8711
  return decoded;
8712
8712
  }
8713
- var BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
8714
8713
  function toBase64(bytes3) {
8715
- let out = "";
8716
- for (let i = 0; i < bytes3.length; i += 3) {
8717
- const b0 = bytes3[i];
8718
- const b1 = i + 1 < bytes3.length ? bytes3[i + 1] : 0;
8719
- const b2 = i + 2 < bytes3.length ? bytes3[i + 2] : 0;
8720
- out += BASE64_ALPHABET[b0 >> 2 & 63];
8721
- out += BASE64_ALPHABET[(b0 << 4 | b1 >> 4) & 63];
8722
- out += i + 1 < bytes3.length ? BASE64_ALPHABET[(b1 << 2 | b2 >> 6) & 63] : "=";
8723
- out += i + 2 < bytes3.length ? BASE64_ALPHABET[b2 & 63] : "=";
8724
- }
8725
- return out;
8714
+ return toBase64Url(bytes3).replace(/-/g, "+").replace(/_/g, "/").padEnd(Math.ceil(bytes3.length / 3) * 4, "=");
8726
8715
  }
8727
8716
  function fromBase64(value, label) {
8728
8717
  if (!/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(value)) {
8729
8718
  throw new Error(`${label} is invalid`);
8730
8719
  }
8731
- const padding = value.endsWith("==") ? 2 : value.endsWith("=") ? 1 : 0;
8732
- const out = new Uint8Array(value.length / 4 * 3 - padding);
8733
- let outIdx = 0;
8734
- for (let i = 0; i < value.length; i += 4) {
8735
- const v0 = BASE64_ALPHABET.indexOf(value[i]);
8736
- const v1 = BASE64_ALPHABET.indexOf(value[i + 1]);
8737
- const v2 = value[i + 2] === "=" ? 0 : BASE64_ALPHABET.indexOf(value[i + 2]);
8738
- const v3 = value[i + 3] === "=" ? 0 : BASE64_ALPHABET.indexOf(value[i + 3]);
8739
- const b0 = v0 << 2 | v1 >> 4;
8740
- const b1 = (v1 & 15) << 4 | v2 >> 2;
8741
- const b2 = (v2 & 3) << 6 | v3;
8742
- if (outIdx < out.length) out[outIdx++] = b0;
8743
- if (outIdx < out.length) out[outIdx++] = b1;
8744
- if (outIdx < out.length) out[outIdx++] = b2;
8745
- }
8746
- if (toBase64(out) !== value) throw new Error(`${label} is invalid`);
8747
- return out;
8720
+ try {
8721
+ return fromBase64Url(value.replace(/=+$/, "").replace(/\+/g, "-").replace(/\//g, "_"));
8722
+ } catch {
8723
+ throw new Error(`${label} is invalid`);
8724
+ }
8748
8725
  }
8749
8726
  async function digestBytes2(value) {
8750
8727
  return toBase64Url(new Uint8Array(await crypto.subtle.digest("SHA-256", value)));
@@ -8861,16 +8838,16 @@ function matchesInitialCiphertextDigest(bytes3, expected) {
8861
8838
  function canonicalHashHex(value) {
8862
8839
  return hex3(sha2566(new TextEncoder().encode(canonicalize(value))));
8863
8840
  }
8864
- async function aesGcmDecrypt(key, blob) {
8841
+ async function aesGcmDecrypt(key, blob, aad) {
8865
8842
  if (key.length !== 32 || blob.length < 28) throw new Error("encrypted content is malformed");
8866
8843
  const cryptoKey = await crypto.subtle.importKey("raw", key, "AES-GCM", false, ["decrypt"]);
8867
- return new Uint8Array(await crypto.subtle.decrypt({ name: "AES-GCM", iv: blob.slice(0, 12) }, cryptoKey, blob.slice(12)));
8844
+ return new Uint8Array(await crypto.subtle.decrypt({ name: "AES-GCM", iv: blob.slice(0, 12), ...aad && { additionalData: aad } }, cryptoKey, blob.slice(12)));
8868
8845
  }
8869
- async function aesGcmEncrypt(key, plaintext) {
8846
+ async function aesGcmEncrypt(key, plaintext, aad) {
8870
8847
  if (key.length !== 32) throw new Error("encrypted content key is malformed");
8871
8848
  const nonce = crypto.getRandomValues(new Uint8Array(12));
8872
8849
  const cryptoKey = await crypto.subtle.importKey("raw", key, "AES-GCM", false, ["encrypt"]);
8873
- const ciphertext = new Uint8Array(await crypto.subtle.encrypt({ name: "AES-GCM", iv: nonce }, cryptoKey, plaintext));
8850
+ const ciphertext = new Uint8Array(await crypto.subtle.encrypt({ name: "AES-GCM", iv: nonce, ...aad && { additionalData: aad } }, cryptoKey, plaintext));
8874
8851
  const output = new Uint8Array(nonce.length + ciphertext.length);
8875
8852
  output.set(nonce);
8876
8853
  output.set(ciphertext, nonce.length);
@@ -8885,8 +8862,9 @@ function parseV3InlineEncryptedEnvelope(bytes3, expected) {
8885
8862
  }
8886
8863
  if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error("encrypted content envelope is malformed");
8887
8864
  const record = value;
8888
- const allowed = ["v", "networkId", "keyPath", "alg", "keyVersion", "encryptedSymmetricKey", "encryptedSymmetricKeyHash", "ciphertext", "metadata"];
8889
- if (Object.keys(record).some((key) => !allowed.includes(key)) || record.v !== 1 || record.networkId !== expected.encryptionNetwork || record.keyPath !== expected.contentSource.encryptionKeyPath || record.keyPath !== void 0 && record.keyPath !== `share/${expected.shareId}` || record.alg !== "x25519-aes256gcm/v1" || record.keyVersion !== expected.contentSource.keyVersion || typeof record.encryptedSymmetricKey !== "string" || typeof record.encryptedSymmetricKeyHash !== "string" || record.encryptedSymmetricKeyHash !== expected.contentSource.encryptedSymmetricKeyDigestHex || record.encryptedSymmetricKeyHash !== canonicalHashHex(record.encryptedSymmetricKey) || typeof record.ciphertext !== "string" || record.metadata !== void 0 && (record.metadata === null || typeof record.metadata !== "object" || Array.isArray(record.metadata) || Object.values(record.metadata).some((entry) => typeof entry !== "string"))) {
8865
+ const allowed = ["v", "networkId", "keyPath", "alg", "keyVersion", "encryptedSymmetricKey", "encryptedSymmetricKeyHash", "ciphertext", "aad", "metadata"];
8866
+ const source = expected.contentSource;
8867
+ if (Object.keys(record).some((key) => !allowed.includes(key)) || record.v !== (source.encryptionKeyPath === void 0 ? 1 : 2) || record.networkId !== source.encryptionNetwork || record.networkId !== expected.encryptionNetwork || record.keyPath !== source.encryptionKeyPath || record.keyPath !== void 0 && record.keyPath !== `share/${expected.shareId}` || record.alg !== "x25519-aes256gcm/v1" || record.keyVersion !== source.keyVersion || typeof record.encryptedSymmetricKey !== "string" || typeof record.encryptedSymmetricKeyHash !== "string" || hex3(sha2566(fromBase64(record.encryptedSymmetricKey, "v3 encrypted symmetric key"))) !== source.encryptedSymmetricKeyDigestHex || record.encryptedSymmetricKeyHash !== canonicalHashHex(record.encryptedSymmetricKey) || typeof record.ciphertext !== "string" || record.aad !== void 0 && typeof record.aad !== "string" || record.metadata !== void 0 && (record.metadata === null || typeof record.metadata !== "object" || Array.isArray(record.metadata) || Object.values(record.metadata).some((entry) => typeof entry !== "string"))) {
8890
8868
  throw new Error("encrypted content envelope binding is invalid");
8891
8869
  }
8892
8870
  return record;
@@ -9007,7 +8985,7 @@ var ShareRecipientClient = class {
9007
8985
  this.session = { sessionId: delegation.sessionCid, expiresAt: new Date(compact.payload.exp * 1e3).toISOString(), actions: envelope.actions, resource: envelope.resource };
9008
8986
  return this.session;
9009
8987
  }
9010
- /** Decrypt a v3 KV value through a fresh recipient-signed decrypt invocation. */
8988
+ /** Decrypt unscoped v1 or path-bound v2 content, independently checking canonical and registered raw-key digests. */
9011
8989
  async decryptV3Content(bytes3) {
9012
8990
  const envelope = this.options.envelope;
9013
8991
  const signer = this.nativeSigner ?? this.signer;
@@ -9015,6 +8993,9 @@ var ShareRecipientClient = class {
9015
8993
  assertArtifactBinding(artifactBindingView(envelope));
9016
8994
  if (!matchesInitialCiphertextDigest(bytes3, envelope.contentSource.initialCiphertextDigestHex)) throw new Error("v3 owner KV ciphertext digest mismatch");
9017
8995
  const encrypted = parseV3InlineEncryptedEnvelope(bytes3, envelope);
8996
+ const ciphertext = fromBase64(encrypted.ciphertext, "v3 encrypted content");
8997
+ if (ciphertext.length < 28) throw new Error("encrypted content is malformed");
8998
+ const aad = encrypted.aad === void 0 ? void 0 : fromBase64(encrypted.aad, "v3 encrypted content AAD");
9018
8999
  const receiverPrivateKey = crypto.getRandomValues(new Uint8Array(32));
9019
9000
  const receiverPublicKey = toBase64(x25519.getPublicKey(receiverPrivateKey));
9020
9001
  const receiverPublicKeyHash = canonicalHashHex(receiverPublicKey);
@@ -9051,7 +9032,7 @@ var ShareRecipientClient = class {
9051
9032
  const symmetricKey = await aesGcmDecrypt(shared, wrapped.slice(33));
9052
9033
  shared.fill(0);
9053
9034
  if (symmetricKey.length !== 32) throw new Error("v3 content key is malformed");
9054
- const plaintext = await aesGcmDecrypt(symmetricKey, fromBase64(encrypted.ciphertext, "v3 encrypted content"));
9035
+ const plaintext = await aesGcmDecrypt(symmetricKey, ciphertext, aad);
9055
9036
  this.v3ContentKey?.fill(0);
9056
9037
  this.v3ContentKey = symmetricKey;
9057
9038
  this.v3ContentEnvelope = encrypted;
@@ -9063,7 +9044,9 @@ var ShareRecipientClient = class {
9063
9044
  /** Re-encrypt edited v3 content with the admitted content key. */
9064
9045
  async encryptV3Content(bytes3, mediaType) {
9065
9046
  if (this.options.envelope.version !== 3 || this.v3ContentKey === void 0 || this.v3ContentEnvelope === void 0) throw new Error("v3 content must be decrypted before it can be saved");
9066
- return new TextEncoder().encode(canonicalize({ ...this.v3ContentEnvelope, ciphertext: toBase64Url(await aesGcmEncrypt(this.v3ContentKey, bytes3)), metadata: { ...this.v3ContentEnvelope.metadata ?? {}, contentType: mediaType } }));
9047
+ const envelope = this.v3ContentEnvelope;
9048
+ const aad = envelope.aad === void 0 ? void 0 : fromBase64(envelope.aad, "v3 encrypted content AAD");
9049
+ return new TextEncoder().encode(canonicalize({ ...envelope, ciphertext: toBase64(await aesGcmEncrypt(this.v3ContentKey, bytes3, aad)), metadata: { ...envelope.metadata ?? {}, contentType: mediaType } }));
9067
9050
  }
9068
9051
  async resumeWithProof(envelope, resumeToken, proof) {
9069
9052
  void envelope;