@socialgouv/e2esdk-client
Advanced tools
Comparing version
@@ -5,6 +5,44 @@ import { PermissionFlags } from '@socialgouv/e2esdk-api'; | ||
/** | ||
* Configuration object for the e2esdk client constructor | ||
*/ | ||
type ClientConfig<KeyType = string> = { | ||
/** | ||
* Fully qualified URL to the e2esdk server | ||
* | ||
* As found in the server's .env configuration, under `DEPLOYMENT_URL`. | ||
*/ | ||
serverURL: string; | ||
/** | ||
* Serialised server signature public key | ||
* | ||
* As found in the server's .env configuration, under `SIGNATURE_PUBLIC_KEY` | ||
* This is used to establish mutual authentication of API calls, | ||
* so that the client can verify authenticity of responses coming | ||
* from the server, and detect MitM tampering. | ||
*/ | ||
serverSignaturePublicKey: KeyType; | ||
/** | ||
* Enable real-time sync with WebSockets for this instance | ||
* | ||
* This defaults to `true` for most cases where there is a single client | ||
* instance in the application. | ||
* Devtools have it set to false when creating their own client instance, | ||
* in order to avoid feedback loops when local-syncing with the main client. | ||
*/ | ||
handleNotifications?: boolean; | ||
/** | ||
* Enable automatic re-authentication on 401 Unauthorized API responses | ||
* | ||
* The default auth session TTL is short-lived (1 hour), so re-authentication | ||
* is necessary, and can be automated using this flag. | ||
* Upon reception of a 401 response status code, the client will attempt to | ||
* login again to refresh its session, and retry the failed operation, | ||
* up to 3 times, after which an error will be thrown. | ||
* | ||
* This defaults to true, and should follow the value of `handleNotifications`: | ||
* true for one main client instance, and false for replicas. | ||
* | ||
* Devtools with their own client don't automatically re-authenticate on 401s. | ||
*/ | ||
handleSessionRefresh?: boolean; | ||
@@ -16,5 +54,5 @@ }; | ||
declare const keychainItemSchema: z.ZodObject<{ | ||
name: z.ZodString; | ||
nameFingerprint: z.ZodString; | ||
payloadFingerprint: z.ZodString; | ||
keychainName: z.ZodString; | ||
keychainFingerprint: z.ZodString; | ||
keyFingerprint: z.ZodString; | ||
cipher: z.ZodEffects<z.ZodString, { | ||
@@ -36,5 +74,5 @@ publicKey: Uint8Array; | ||
}, "strip", z.ZodTypeAny, { | ||
name: string; | ||
nameFingerprint: string; | ||
payloadFingerprint: string; | ||
keychainName: string; | ||
keychainFingerprint: string; | ||
keyFingerprint: string; | ||
cipher: { | ||
@@ -56,5 +94,5 @@ publicKey: Uint8Array; | ||
}, { | ||
name: string; | ||
nameFingerprint: string; | ||
payloadFingerprint: string; | ||
keychainName: string; | ||
keychainFingerprint: string; | ||
keyFingerprint: string; | ||
cipher: string; | ||
@@ -66,6 +104,6 @@ createdAt: string; | ||
type KeychainItem = z.infer<typeof keychainItemSchema>; | ||
type KeychainItemMetadata = Pick<KeychainItem, 'nameFingerprint' | 'payloadFingerprint' | 'createdAt' | 'expiresAt' | 'sharedBy'> & { | ||
type KeychainItemMetadata = Pick<KeychainItem, 'keychainFingerprint' | 'keyFingerprint' | 'createdAt' | 'expiresAt' | 'sharedBy'> & { | ||
algorithm: Cipher['algorithm']; | ||
publicKey?: string; | ||
label: string; | ||
purpose: string; | ||
}; | ||
@@ -86,2 +124,19 @@ type PublicUserIdentity = { | ||
}; | ||
/** | ||
* The main e2esdk client interface | ||
* | ||
* This performs all the cryptographic operations required to implement E2EE | ||
* in your application, along with a deployed server for persistance and | ||
* coordination with other clients. | ||
* | ||
* It requires a little configuration to connect it to a running e2esdk server, | ||
* and enable public-key based mutual authentication of API calls. | ||
* | ||
* Multiple clients instanciated on the same origin will sync their state: | ||
* a successfull login on one will enable the others to perform actions, | ||
* making multi-tab applications seamless. | ||
* | ||
* Clients react in real-time to server-sent events, and sync their keystore | ||
* automatically. You can subscribe to events using the .on() method. | ||
*/ | ||
declare class Client { | ||
@@ -91,14 +146,123 @@ #private; | ||
readonly config: Readonly<Config>; | ||
/** | ||
* Create a new instance of the e2esdk client | ||
* | ||
* This operation is generally safe to perform on the server in SSR contexts, | ||
* however most other operations will require to run in a browser environment, | ||
* and require authentication. | ||
* | ||
* @param config Client configuration object | ||
*/ | ||
constructor(config: ClientConfig); | ||
/** | ||
* Subscribe to events | ||
* | ||
* @param event the event name to subscribe to, see available {@link Events} | ||
* @param callback pass a callback function with the appropriate payload | ||
* @returns an unsubscribe function, to be called to stop listening | ||
* | ||
* Example: | ||
* ```ts | ||
* // Subscribe to identity changes: | ||
* const off = client.on('identityUpdated', identity => { | ||
* if (identity) { | ||
* console.log(identity.userId) | ||
* } else { | ||
* // logged out | ||
* } | ||
* }) | ||
* // Unsubscribe | ||
* off() | ||
* ``` | ||
*/ | ||
on<K extends keyof Events>(event: K, callback: (arg: Events[K]) => void): () => void; | ||
/** | ||
* Create an identity on e2esdk | ||
* | ||
* @param userId a unique, immutable identifier for a user in the application. | ||
* Ideally, this should be an automatically generated primary key in the | ||
* application database, like a UUID. | ||
* | ||
* This will do a couple of things: | ||
* 1. Create an identity derived from a newly generated mainKey | ||
* 2. Register a device pre-enrolled to this account | ||
* 3. Persist those objects on the server | ||
* | ||
* Note that signup does not authenticate the user, you will need to call | ||
* the `login` method after a successful signup to establish an authenticated | ||
* session. | ||
*/ | ||
signup(userId: string): Promise<void>; | ||
/** | ||
* Authenticate using the local enrolled device authentication | ||
* | ||
* @param userId The user ID used at registration (signup) time | ||
* @returns A Promise to the public user identity if the login succeeds, | ||
* or null if it fails. | ||
* | ||
* It may seem weird that only the userId is required to authenticate, | ||
* but that's a side effect of using enrolled devices for access: the | ||
* actual credentials are stored on each device, the user ID is only a | ||
* way to handle multiple accounts on a single physical storage context | ||
* (eg: alice & bob sharing the same Firefox browser). | ||
* | ||
* When logging in, the device credentials will be retrieved from | ||
* local storage, and used to perform an OPAQUE authentication flow. | ||
* Out of that, the OPAQUE export key will be used to unwrap the | ||
* user account mainKey, from which the user identity will be derived. | ||
* The OPAQUE key agreement also defines the session ID. | ||
* | ||
* Once the client is hydrated with an identity and a session ID, it can | ||
* perform authenticated calls to the API. | ||
*/ | ||
login(userId: string): Promise<PublicUserIdentity | null>; | ||
/** | ||
* Revoke the current authentication session | ||
* | ||
* This will clear all local state and lock up the client. | ||
* A login step will be necessary to further resume authenticated operations. | ||
*/ | ||
logout(): void; | ||
/** | ||
* On an active device, prepare to enroll another device. | ||
* | ||
* This will retrieve the user account mainKey, generate a set of OPAQUE | ||
* credentials for the new device, perform an OPAQUE registration to obtain | ||
* an export key, and wrap the mainKey with it. The credentials are then | ||
* returned to the application to be transmitted to the new device for | ||
* final registration. | ||
* | ||
* @see {@link registerEnrolledDevice `registerEnrolledDevice`}, to be | ||
* called on the new device with the registration URI string returned by | ||
* this method. Transmission is left to the application, though an offline | ||
* delivery method (eg: scanning a QR code) is recommended. | ||
* | ||
* @authenticated This method requires authentication | ||
* | ||
* @param label Optional name to give the device, for later identification. | ||
* Will be end-to-end encrypted when persisted on the server. | ||
* @returns A Promise to a registration URI string to send to the enrolled device. | ||
*/ | ||
enrollNewDevice(label?: string): Promise<string>; | ||
/** | ||
* Register this device and login | ||
* @param uri device registration URI | ||
* | ||
* Registration means saving the given credentials into local storage, | ||
* so that the login process can use them for authentication. | ||
* | ||
* In and out of itself, this method wouldn't do much, so it also attempts | ||
* to login to establish a session, as it would be the next logical step. | ||
* | ||
* @param uri device registration URI, as obtained from a call to | ||
* {@link enrollNewDevice `enrollNewDevice`} on the originating device. | ||
*/ | ||
registerEnrolledDevice(uri: string): Promise<PublicUserIdentity | null>; | ||
get currentDeviceId(): string | null; | ||
/** | ||
* Retrieve a list of currently enrolled devices for this account. | ||
* | ||
* Also includes active session information for each device. | ||
* | ||
* @authenticated This method requires authentication | ||
*/ | ||
getEnrolledDevices(): Promise<{ | ||
@@ -114,16 +278,139 @@ label: string | undefined; | ||
}[]>; | ||
createKey(label: string, algorithm: 'secretBox' | 'sealedBox', expiresAt?: Date): Promise<KeychainItemMetadata>; | ||
rotateKey(nameFingerprint: string, expiresAt?: Date): Promise<KeychainItemMetadata>; | ||
/** | ||
* Create a new keychain for a given purpose, with an initial key (or key pair) | ||
* | ||
* This will create a key of the given algorithm, and attach it to a new | ||
* keychain, labelled with the given purpose. | ||
* | ||
* Note that two calls to this method with the same `purpose` will generate | ||
* different keychains (different `keychainFingerprint` values). | ||
* | ||
* If you want to rotate an existing key, use {@link rotateKey `rotateKey`}. | ||
* | ||
* @param purpose What this keychain will be used for, to let your application | ||
* retrieve it later. | ||
* @param algorithm `secretBox` for symmetric encryption, `sealedBox` for form data. | ||
* // todo: Add link to online docs that explains the difference | ||
* @param expiresAt Optional expiration date for the initial key | ||
* | ||
* @authenticated This method requires authentication | ||
*/ | ||
createNewKeychain(purpose: string, algorithm: 'secretBox' | 'sealedBox', expiresAt?: Date): Promise<KeychainItemMetadata>; | ||
/** | ||
* Add a new key to an existing keychain, replacing the older one | ||
* for encryption operations. | ||
* | ||
* Previous keys remain available in the keychain for decryption operations. | ||
* | ||
* @param keychainFingerprint | ||
* @param expiresAt Optional expiration date for the new key | ||
* | ||
* @authenticated This method requires authentication | ||
*/ | ||
rotateKey(keychainFingerprint: string, expiresAt?: Date): Promise<KeychainItemMetadata>; | ||
/** | ||
* Get a record of available keys. | ||
* | ||
* @returns a record object keyed by the keychainFingerprint and whose values | ||
* are arrays of keys, most recent first (the one used for encryption). | ||
* | ||
* @authenticated This accessor requires authentication | ||
*/ | ||
get keys(): Record<string, KeychainItemMetadata[]>; | ||
findKeyByNameFingerprint(nameFingerprint: string): KeychainItemMetadata | undefined; | ||
findKeyByLabel(label: string): KeychainItemMetadata | undefined; | ||
deleteKey(nameFingerprint: string, payloadFingerprint: string): Promise<void>; | ||
shareKey(nameFingerprint: string, to: PublicUserIdentity, { expiresAt }?: ShareKeyOptions): Promise<void>; | ||
/** | ||
* Find the most recent key (to use for encryption) for a given keychainFingerprint. | ||
* | ||
* Server-provided data uses the keychainFingerprint to identify purposes, | ||
* so this method can be used to retrieve a key based on that data. | ||
* | ||
* @authenticated This method requires authentication | ||
* (will return `undefined` if unauthenticated) | ||
*/ | ||
findKeyByKeychainFingerprint(keychainFingerprint: string): KeychainItemMetadata | undefined; | ||
/** | ||
* Find the most recent key (to use for encryption) for a given purpose. | ||
* | ||
* @authenticated This method requires authentication | ||
* (will return `undefined` if unauthenticated) | ||
*/ | ||
findKeyByPurpose(purpose: string): KeychainItemMetadata | undefined; | ||
/** | ||
* Delete a specific key | ||
* | ||
* This will remove it both on the client's keychain and erase its record | ||
* on the server, and sync up other devices and clients for this user. | ||
* | ||
* @authenticated This method requires authentication | ||
* | ||
*/ | ||
deleteKey(keychainFingerprint: string, keyFingerprint: string): Promise<void>; | ||
/** | ||
* Share only the most recent key in the given keychain with another e2esdk user. | ||
* | ||
* To share a specific key in a specific keychain, use {@link shareKey `shareKey`}. | ||
* To share the whole keychain, use {@link shareCompleteKeychain `shareCompleteKeychain`}. | ||
* | ||
* @param keychainFingerprint keychain to share (only the latest key) | ||
* @param shareWith Public identity of the user to share the key with | ||
* (only the user ID and sharing public key are required) | ||
* @param options Optional bag of options (key expiration, etc..) | ||
* | ||
* @authenticated This method requires authentication | ||
*/ | ||
shareMostRecentKey(keychainFingerprint: string, shareWith: Pick<PublicUserIdentity, 'userId' | 'sharingPublicKey'>, options?: ShareKeyOptions): Promise<void>; | ||
/** | ||
* Share all the keys available in a keychain with another e2esdk user. | ||
* | ||
* This may be useful to give complete access to a newcoming user in a | ||
* shared workspace. | ||
* | ||
* Note however that only the keys you possess will be shared. If other users | ||
* have a more extended keychain, their extra keys won't be shared. | ||
* | ||
* @param keychainFingerprint keychain to send to the user | ||
* @param shareWith Public identity of the user to share the key with | ||
* (only the user ID and sharing public key are required) | ||
* @param options Optional bag of options (key expiration, etc..) | ||
* | ||
* @authenticated This method requires authentication | ||
*/ | ||
shareCompleteKeychain(keychainFingerprint: string, shareWith: Pick<PublicUserIdentity, 'userId' | 'sharingPublicKey'>, options?: ShareKeyOptions): Promise<void>; | ||
/** | ||
* Share a specific key in a specific keychain with a specific e2esdk user. | ||
* | ||
* To share the latest key in a specific keychain, use {@link shareMostRecentKey `shareMostRecentKey`}. | ||
* To share the whole keychain, use {@link shareCompleteKeychain `shareCompleteKeychain`}. | ||
* | ||
* @param keychainFingerprint keychain where to find the key | ||
* @param keyFingerprint fingerprint of the key to share | ||
* @param shareWith Public identity of the user to share the key with | ||
* (only the user ID and sharing public key are required) | ||
* @param options Optional bag of options (key expiration, etc..) | ||
* | ||
* @authenticated This method requires authentication | ||
*/ | ||
shareKey(keychainFingerprint: string, keyFingerprint: string, shareWith: Pick<PublicUserIdentity, 'userId' | 'sharingPublicKey'>, { expiresAt }?: ShareKeyOptions): Promise<void>; | ||
/** | ||
* List pending shared keys from this user to others | ||
* | ||
* @authenticated This method requires authentication | ||
*/ | ||
getOutgoingSharedKeys(): Promise<{ | ||
createdAt: string; | ||
nameFingerprint: string; | ||
expiresAt: string | null; | ||
name: string; | ||
payload: string; | ||
payloadFingerprint: string; | ||
keychainFingerprint: string; | ||
expiresAt: string | null; /** | ||
* Register this device and login | ||
* | ||
* Registration means saving the given credentials into local storage, | ||
* so that the login process can use them for authentication. | ||
* | ||
* In and out of itself, this method wouldn't do much, so it also attempts | ||
* to login to establish a session, as it would be the next logical step. | ||
* | ||
* @param uri device registration URI, as obtained from a call to | ||
* {@link enrollNewDevice `enrollNewDevice`} on the originating device. | ||
*/ | ||
encryptedKeychainName: string; | ||
encryptedKey: string; | ||
keyFingerprint: string; | ||
signature: string; | ||
@@ -136,7 +423,46 @@ toUserId: string; | ||
}[]>; | ||
deleteOutgoingSharedKey(toUserId: string, payloadFingerprint: string): Promise<void>; | ||
/** | ||
* Cancel sharing a key with someone else | ||
* | ||
* @authenticated This method requires authentication | ||
*/ | ||
deleteOutgoingSharedKey(toUserId: string, keyFingerprint: string): Promise<void>; | ||
/** | ||
* Get the identity of the currently logged-in user, or `null` if unauthenticated. | ||
*/ | ||
get publicIdentity(): PublicUserIdentity | null; | ||
/** | ||
* Obtain the identity of a particular user | ||
* | ||
* This will ask the server for the public record of identity for the given | ||
* userId, and verify its proof. | ||
* | ||
* To lookup multiple users at once, use {@link getUsersIdentities `getUserIdentities`}. | ||
* | ||
* @param userId The user ID to lookup | ||
* @returns a Promise to the identity, or `null` if not found or invalid proof. | ||
* | ||
* @authenticated This method requires authentication | ||
*/ | ||
getUserIdentity(userId: string): Promise<PublicUserIdentity | null>; | ||
/** | ||
* Lookup multiple user identities in one go. | ||
* | ||
* To lookup a single user, use {@link getUserIdentity `getUserIdentity`}. | ||
* | ||
* @param userIds a list of user ID to lookup | ||
* | ||
* @authenticated This method requires authentication | ||
*/ | ||
getUsersIdentities(userIds: string[]): Promise<PublicUserIdentity[]>; | ||
getParticipants(nameFingerprint: string, payloadFingerprint: string): Promise<{ | ||
/** | ||
* List users with access to a given key | ||
* | ||
* @param keychainFingerprint keychain fingerprint to lookup | ||
* @param keyFingerprint fingerprint of a particular key in the keychain | ||
* @returns an array of identities, permissions and other metadata | ||
* | ||
* @authenticated This method requires authentication | ||
*/ | ||
getParticipants(keychainFingerprint: string, keyFingerprint: string): Promise<{ | ||
userId: string; | ||
@@ -153,3 +479,10 @@ sharingPublicKey: string; | ||
}[]>; | ||
getPermissions(nameFingerpint: string): Promise<{ | ||
/** | ||
* Get your own permissions for a given keychain | ||
* | ||
* @param keychainFingerprint keychain fingerprint to lookup | ||
* | ||
* @authenticated This method requires authentication | ||
*/ | ||
getPermissions(keychainFingerprint: string): Promise<{ | ||
allowSharing: boolean; | ||
@@ -160,10 +493,138 @@ allowRotation: boolean; | ||
}>; | ||
setPermissions(userId: string, nameFingerprint: string, permissions: Partial<PermissionFlags>): Promise<void>; | ||
banUser(userId: string, nameFingerprint: string): Promise<void>; | ||
encrypt<DataType>(input: DataType, nameFingerprint: string, additionalData?: string | Uint8Array): string; | ||
decrypt(ciphertext: string, nameFingerpint: string, additionalData?: string | Uint8Array): unknown; | ||
unsealFormData<FormData extends object>(submission: EncryptedFormSubmission<FormData>, nameFingerpint: string): Record<keyof FormData, unknown>; | ||
/** | ||
* Change permissions for another participant of a keychain | ||
* | ||
* This call will succeed only if you have the `allowManagement` permission | ||
* for the given keychain. | ||
* Note that you may apply permissions to yourself as well, including | ||
* revoking your `allowManagement` permission. If no other participant has | ||
* this right, permissions won't be able to be changed! | ||
* | ||
* @param userId User ID for whom to set permissions | ||
* @param keychainFingerprint Keychain fingerprint to apply the permissions to | ||
* @param permissions Partial object with boolean permissions to apply | ||
* | ||
* @authenticated This method requires authentication | ||
*/ | ||
setPermissions(userId: string, keychainFingerprint: string, permissions: Partial<PermissionFlags>): Promise<void>; | ||
/** | ||
* Revoke access to the given keychain for a user. | ||
* | ||
* This requires the `allowDeletion` permission on the keychain | ||
* for the calling user. | ||
* | ||
* You can always ban yourself off of a keychain, regardless of permissions, | ||
* to allow cleaning up. Use this to remove all traces of a keychain | ||
* from your account. | ||
* | ||
* Note: banning does **not** perform key rotation. | ||
* If banning a user for security reasons, it is recommended to rotate | ||
* the current encryption key for all other remaining participants. | ||
* | ||
* The workflow is as such: | ||
* 1. Ban the user from the keychain using this method | ||
* 2. Rotate the key using {@link rotateKey} | ||
* 3. Obtain the list of participants for the keychain with {@link getParticipants} | ||
* 4. Share the latest key with the remaining participants using {@link shareMostRecentKey} | ||
* | ||
* @param userId user ID to ban | ||
* @param keychainFingerprint keychain fingerprint to remove access to | ||
* | ||
* @authenticated This method requires authentication | ||
*/ | ||
banUser(userId: string, keychainFingerprint: string): Promise<void>; | ||
/** | ||
* Encrypt arbitrary data | ||
* | ||
* The algorithm will depend upon the keychain type, though this is mostly | ||
* useful for symmetric cryptography, using `secretBox` keys. | ||
* | ||
* @param input arbitrary data | ||
* (strings, numbers, objects, arrays, as long as it's JSON-serialisable) | ||
* @param keychainFingerprint which keychain to use for encryption | ||
* (the most recent key will be used) | ||
* @param additionalData Extra authenticated data that is not encrypted, but | ||
* that must be presented as-is for decryption to succeed. | ||
* This allows binding the ciphertext to a particular context. | ||
* See https://en.wikipedia.org/wiki/Authenticated_encryption | ||
* @returns a string containing the encoded ciphertext and metadata | ||
* | ||
* @authenticated This method requires authentication | ||
*/ | ||
encrypt<DataType>(input: DataType, keychainFingerprint: string, additionalData?: string | Uint8Array): string; | ||
/** | ||
* Decrypt arbitrary data | ||
* | ||
* Note: to decrypt form data, use {@link unsealFormData `unsealFormData`}. | ||
* | ||
* This will try decrypting a given ciphertext string against all available | ||
* keys in the specified keychain. If all keys are exhausted without success, | ||
* an error will be thrown. | ||
* | ||
* @param input arbitrary data | ||
* (strings, numbers, objects, arrays, as long as it's JSON-serialisable) | ||
* @param keychainFingerprint which keychain to use for encryption | ||
* (the most recent key will be used) | ||
* @param additionalData Extra authenticated data that was not encrypted, but | ||
* that must be presented as-is for decryption to succeed. | ||
* This allows binding the ciphertext to a particular context. | ||
* See https://en.wikipedia.org/wiki/Authenticated_encryption | ||
* @returns an unknown type: you must pass this through a parser that ensures | ||
* the clear text data conforms to a specific type, in order to prevent | ||
* from untrusted inputs. | ||
* | ||
* @authenticated This method requires authentication | ||
*/ | ||
decrypt(ciphertext: string, keychainFingerprint: string, additionalData?: string | Uint8Array): unknown; | ||
/** | ||
* Decrypt form data encrypted with `encryptFormData`. | ||
* | ||
* @param submission encrypted form data & associated cryptographic metadata | ||
* @param keychainFingerprint keychain to use for decryption | ||
* @returns a record of unknown values: you must pass the result through a | ||
* parser that ensures form data conforms to a specific type, to avoid and | ||
* reject untrusted / malformed data submissions. | ||
* | ||
* @authenticated This method requires authentication | ||
*/ | ||
unsealFormData<FormData extends object>(submission: EncryptedFormSubmission<FormData>, keychainFingerprint: string): Record<keyof FormData, unknown>; | ||
/** | ||
* Sign an arbitrary array of string items against the user's identity | ||
* | ||
* This should be used with care, especially if dealing with untrusted | ||
* user-provided inputs, even though the underlying signature algorithm | ||
* has protections against canonicalization attacks. | ||
* | ||
* Note: the order of items must be the same for signature and verification! | ||
* | ||
* @param items List of items to generate a signature for | ||
* @returns a base64url-encoded signature string | ||
* | ||
* @authenticated This method requires authentication | ||
*/ | ||
sign(...items: string[]): string; | ||
/** | ||
* Verify the signature of an arbitrary array of string items | ||
* against a given user's identity. | ||
* | ||
* This should be used with care, especially if dealing with untrusted | ||
* user-provided inputs, even though the underlying signature algorithm | ||
* has protections against canonicalization attacks. | ||
* | ||
* Note: the order of items must be the same for signature and verification! | ||
* | ||
* @param signature Signature string as obtained from {@link sign `sign`}. | ||
* @param publicKey Signature public key of the alleged author | ||
* (part of the public identity). Can be provided as base64url or byte array. | ||
* @param items List of items to verify the signature against | ||
* @returns true if the signature is valid, false otherwise. | ||
*/ | ||
verifySignature(signature: string, publicKey: string | Uint8Array, ...items: string[]): boolean; | ||
/** | ||
* Encode the input byte array to base64url | ||
*/ | ||
encode(input: Uint8Array): string; | ||
/** | ||
* Decode a base64url-encoded string into a byte array | ||
*/ | ||
decode(input: string): Uint8Array; | ||
@@ -170,0 +631,0 @@ } |
{ | ||
"name": "@socialgouv/e2esdk-client", | ||
"version": "1.0.0-beta.26", | ||
"version": "1.0.0-beta.27", | ||
"license": "Apache-2.0", | ||
@@ -44,4 +44,4 @@ "description": "End-to-end encryption client", | ||
"@47ng/opaque-client": "^2.1.5", | ||
"@socialgouv/e2esdk-api": "^1.0.0-beta.12", | ||
"@socialgouv/e2esdk-crypto": "^1.0.0-beta.18", | ||
"@socialgouv/e2esdk-api": "^1.0.0-beta.13", | ||
"@socialgouv/e2esdk-crypto": "^1.0.0-beta.19", | ||
"local-state-sync": "1.0.0-beta.6", | ||
@@ -48,0 +48,0 @@ "mitt": "^3.0.0", |
@@ -1,1 +0,1 @@ | ||
{"$schema":"https://raw.githubusercontent.com/47ng/sceau/main/src/schemas/v1.schema.json","signature":"405f3c08044c4ad4200d184e225840cacd9cda6f529789e0f7d4898ec21bcafa4d34f747eb2806beed7e19de8224b5f68ee737d584c86099be080f853bb73e08","publicKey":"82182691aa16fb18c4ee5f502f9067fe486768391d6ad5baa95e7a68913c9ad9","timestamp":"2023-05-12T08:08:54.595Z","sourceURL":"https://github.com/SocialGouv/e2esdk/tree/7011205faaa59271f150aa45152d4d10f59dc788","buildURL":"https://github.com/SocialGouv/e2esdk/actions/runs/4956565442","manifest":[{"path":"README.md","hash":"4d045827bb62a85317c226a17beb8fcced4f7464c9cd98b1a9f5454f189d6a5e41da42f1b52183dfe66f166371e9caafb80f170af967d8c7b8999fecd6751c0b","sizeBytes":184,"signature":"73db42e6419b8c7b628e73c87229c182557c258a4ec4ed8a270cb01658fbf7b8d1289288d543bf6a8ec85c9f3836ef8d70f7cba18b38604b128b3973d5bcd009"},{"path":"dist/index.cjs","hash":"20bdd18f37fae1b3ebe591bb98bb375edd0c3ce5984dde8ec9b0f3f45bd463360ede7c4be71c8c55ec0de7d3c72f02edb8b6fe51155afa4ebba973471a48f32d","sizeBytes":48594,"signature":"0951700c9a7a230c73145d71a9ecf970f70b36ac8d58697f5e5722c0ae044cae5f32cc3bfc892d30892abb02a270c3ea191513c14f91178ffe3d2865e0872109"},{"path":"dist/index.d.ts","hash":"fed6d92f381f2293fdcea02490e975a2f821d0db419efa7551c4514490a35e2135d97e785ee9a58a58be3bc89134d07c9c095e6fc16983d907d002f6b04dfca0","sizeBytes":6182,"signature":"3195092302f3c0f0703fa11502c31106a09a6c772ae305afa0d599b851e5973f5448dcd29f71701c613a2e00dc480ae3275bc6063b42caa72074190ea027510e"},{"path":"dist/index.js","hash":"ec640a1d0cec4b22e9a24fbee1f43c6ab825d70e7167d5c791d4097d501b8e340a85ed8af0fccc5281416b7ad8780e7f2e31cab75402af114577c6b250f98501","sizeBytes":47304,"signature":"45b5c43357aa0e30b6c22311d61fe74c55589e2594422ec6b716417c38609a9ec13613a225216e9bf4443e6820d6b69288301cbb45fde10f02d5af22537a8702"},{"path":"package.json","hash":"5763211cef817029540d7d140873c09c54c48caeefddc35234f1003a88064d653e15a65e210f4cd0fbc0382c2e3970257e6768425952498cbccdde307099050b","sizeBytes":1352,"signature":"54614dbfbcfec768ac14b5e56f18c26d35c84220240f715119870b0fca3ec6638139bd518cac302a0a789984f01d9ded26ceedefaa6f8cd1b965674c75c52204"}]} | ||
{"$schema":"https://raw.githubusercontent.com/47ng/sceau/main/src/schemas/v1.schema.json","signature":"01b9d4d1923c506e5935a2b3d4c83df0fce0c14eb0d9383e3965e5fa714054dfcb5af68e2d4e9058885f0ffe5090d5070a2909468a77b2c4c4e8b9ca4980c60c","publicKey":"82182691aa16fb18c4ee5f502f9067fe486768391d6ad5baa95e7a68913c9ad9","timestamp":"2023-06-09T08:57:38.224Z","sourceURL":"https://github.com/SocialGouv/e2esdk/tree/5541d404ad8df976dc9ccfba1305ad0d20648004","buildURL":"https://github.com/SocialGouv/e2esdk/actions/runs/5220055014","manifest":[{"path":"README.md","hash":"4d045827bb62a85317c226a17beb8fcced4f7464c9cd98b1a9f5454f189d6a5e41da42f1b52183dfe66f166371e9caafb80f170af967d8c7b8999fecd6751c0b","sizeBytes":184,"signature":"73db42e6419b8c7b628e73c87229c182557c258a4ec4ed8a270cb01658fbf7b8d1289288d543bf6a8ec85c9f3836ef8d70f7cba18b38604b128b3973d5bcd009"},{"path":"dist/index.cjs","hash":"ef4d9761b966ff95499b96b86565c0dd210caf4879f30043667f8e6466c0b58d42541ef24126885ef8dd8bfc084be5d540e4cbc911b4b8d89faf384c641a762a","sizeBytes":67418,"signature":"bb8cac21c44ba4444c39b13684484701371d0e8eef7e305173d33e4dd0e9339896d143352670852a9d1c4fecf83851165ffeb3d0bd2ff87e90d381cf19a2d10c"},{"path":"dist/index.d.ts","hash":"084de89f3e91dfccbe9c82dcaf888460f67a0ecedf54eb75d6abd1f4f7520819bd7747045c8191e9ca3cce757c91384b60f41371969409e2250951e4310b0150","sizeBytes":26114,"signature":"5a64446eb1909e66785357e808e4774022bf1b654a7cdfedfad2a50b21a3db8bc6bc9d0d3c2d23ba06035b1472fe95a05721e66263686513ab930f04816c4805"},{"path":"dist/index.js","hash":"de1b2f0355dcbe51752cd0213501dc389e2483cf919697950518c694e5f246d41f0df61eb62c2fbc9e58fedd1de90e095d7a8cbd5ba9feba1f1b4278b0b6328a","sizeBytes":65894,"signature":"4c363f502643f98bea84925b2f8e6a4f0318065f2a8b2650d6e64040be460225562de4611bd37a5ab889f90e8eaafdc9e9c4de1c94cb971be9f7178851224d0c"},{"path":"package.json","hash":"320678ad3270a8c4975c5f5bd900ef42a688442b932ce23c099d30f2c54edf0a43028c2168706eefddf735f8b75b433404a9a64100eee92f9d04792650f42370","sizeBytes":1352,"signature":"15ae0d691018030c2d3e47050cb14031cd8223ee3a88f04af6b870480230e64c2fadbb374554ae8fc6d1fa5c046fde66ec2127d94250021b72bb2abcc2ed8d05"}]} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
163112
54.22%4332
47.9%