@opendatalabs/vana-sdk
Version:
A TypeScript library for interacting with Vana Network smart contracts.
175 lines (174 loc) • 6.24 kB
TypeScript
/**
* ECIES (Elliptic Curve Integrated Encryption Scheme) Interface
*
* @remarks
* Defines the contract for platform-specific ECIES implementations.
* All implementations maintain compatibility with the eccrypto format to ensure
* backward compatibility with existing encrypted data.
*
* **Format specification:**
* `[iv (16 bytes)][ephemPublicKey (65 bytes)][ciphertext (variable)][mac (32 bytes)]`
*
* @category Cryptography
*/
/**
* Represents ECIES encrypted data in eccrypto-compatible format.
*
* @remarks
* This structure maintains backward compatibility with data encrypted using
* the legacy eccrypto library.
*/
export interface ECIESEncrypted {
/** Initialization vector (16 bytes) */
iv: Uint8Array;
/** Ephemeral public key (65 bytes uncompressed) */
ephemPublicKey: Uint8Array;
/** Encrypted data */
ciphertext: Uint8Array;
/** Message authentication code (32 bytes) */
mac: Uint8Array;
}
/**
* Provides ECIES encryption and decryption operations.
*
* @remarks
* Platform-specific implementations handle the underlying cryptographic primitives
* while maintaining consistent data format across environments.
*
* @category Cryptography
*/
export interface ECIESProvider {
/**
* Encrypts data using ECIES with secp256k1.
*
* @param publicKey - Recipient's public key (65 bytes uncompressed or 33 bytes compressed).
* Obtain via `vana.server.getIdentity(userAddress).public_key`.
* @param message - Data to encrypt.
* @returns Encrypted data structure compatible with eccrypto format.
* @throws {ECIESError} When public key is invalid.
* Verify key format matches secp256k1 requirements.
*
* @example
* ```typescript
* const encrypted = await provider.encrypt(
* fromHex(publicKey, 'bytes'),
* new TextEncoder().encode('sensitive data')
* );
* ```
*/
encrypt(publicKey: Uint8Array, message: Uint8Array): Promise<ECIESEncrypted>;
/**
* Decrypts ECIES encrypted data.
*
* @param privateKey - Recipient's private key (32 bytes).
* @param encrypted - Encrypted data structure from `encrypt()` or legacy eccrypto.
* @returns Decrypted message as Uint8Array.
* @throws {ECIESError} When MAC verification fails.
* Ensure the private key matches the public key used for encryption.
*
* @example
* ```typescript
* const decrypted = await provider.decrypt(
* fromHex(privateKey, 'bytes'),
* encrypted
* );
* const message = new TextDecoder().decode(decrypted);
* ```
*/
decrypt(privateKey: Uint8Array, encrypted: ECIESEncrypted): Promise<Uint8Array>;
/**
* Normalizes a public key to uncompressed format (65 bytes with 0x04 prefix).
*
* @remarks
* Strict policy: Only accepts properly formatted compressed (33 bytes) or
* uncompressed (65 bytes) public keys. Does not accept 64-byte raw coordinates
* to ensure data integrity and prevent masking of malformed inputs.
*
* @param publicKey - Public key in compressed or uncompressed format
* @returns Normalized uncompressed public key (65 bytes with 0x04 prefix)
* @throws {Error} When public key format is invalid, including raw coordinates (64 bytes)
* @throws {Error} When decompression of compressed key fails
*
* @example
* ```typescript
* // Compressed key (33 bytes)
* const compressed = new Uint8Array(33);
* compressed[0] = 0x02;
* const uncompressed = provider.normalizeToUncompressed(compressed);
* console.log(uncompressed.length); // 65
* console.log(uncompressed[0]); // 0x04
*
* // Already uncompressed (65 bytes)
* const already = provider.normalizeToUncompressed(uncompressedKey);
* console.log(already === uncompressedKey); // true (returns same reference)
*
* // Raw coordinates rejected (64 bytes)
* const raw = new Uint8Array(64);
* provider.normalizeToUncompressed(raw); // Throws error
* ```
*/
normalizeToUncompressed(publicKey: Uint8Array): Uint8Array;
}
/**
* Configures ECIES operation behavior.
*/
export interface ECIESOptions {
/** Use compressed public keys (33 bytes) instead of uncompressed (65 bytes) */
useCompressed?: boolean;
}
/**
* Represents failures in ECIES cryptographic operations.
*
* @remarks
* Provides specific error codes to help identify and recover from
* different failure scenarios.
*
* @category Errors
*/
export declare class ECIESError extends Error {
readonly code: "INVALID_KEY" | "ENCRYPTION_FAILED" | "DECRYPTION_FAILED" | "MAC_MISMATCH" | "ECDH_FAILED";
readonly cause?: Error | undefined;
constructor(message: string, code: "INVALID_KEY" | "ENCRYPTION_FAILED" | "DECRYPTION_FAILED" | "MAC_MISMATCH" | "ECDH_FAILED", cause?: Error | undefined);
}
/**
* Validates if an object conforms to the ECIESEncrypted structure.
*
* @param obj - Object to validate.
* @returns `true` if object is a valid ECIESEncrypted structure.
*
* @example
* ```typescript
* if (isECIESEncrypted(data)) {
* const decrypted = await provider.decrypt(privateKey, data);
* }
* ```
*/
export declare function isECIESEncrypted(obj: unknown): obj is ECIESEncrypted;
/**
* Serializes ECIESEncrypted to hex string for storage or transmission.
*
* @param encrypted - Encrypted data structure from `encrypt()`.
* @returns Hex string representation.
*
* @example
* ```typescript
* const hexString = serializeECIES(encrypted);
* // Store hexString in database or send over network
* ```
*/
export declare function serializeECIES(encrypted: ECIESEncrypted): string;
/**
* Deserializes hex string to ECIESEncrypted structure.
*
* @param hex - Hex string from `serializeECIES()` or storage.
* @returns ECIESEncrypted structure ready for decryption.
* @throws {ECIESError} When hex string format is invalid.
* Verify the hex string is complete and uncorrupted.
*
* @example
* ```typescript
* const encrypted = deserializeECIES(hexString);
* const decrypted = await provider.decrypt(privateKey, encrypted);
* ```
*/
export declare function deserializeECIES(hex: string): ECIESEncrypted;