@opendatalabs/vana-sdk
Version:
A TypeScript library for interacting with Vana Network smart contracts.
79 lines • 3 kB
JavaScript
import { CIPHER, CURVE, MAC, FORMAT } from "./constants.js";
import { fromHex, toHex } from "viem";
class ECIESError extends Error {
constructor(message, code, cause) {
super(message);
this.code = code;
this.cause = cause;
this.name = "ECIESError";
}
code;
cause;
}
function isECIESEncrypted(obj) {
if (!obj || typeof obj !== "object") return false;
const enc = obj;
const isUint8Array = (value) => {
return value instanceof Uint8Array || typeof Buffer !== "undefined" && Buffer.isBuffer(value);
};
return isUint8Array(enc.iv) && enc.iv.length === CIPHER.IV_LENGTH && isUint8Array(enc.ephemPublicKey) && (enc.ephemPublicKey.length === CURVE.UNCOMPRESSED_PUBLIC_KEY_LENGTH || enc.ephemPublicKey.length === CURVE.COMPRESSED_PUBLIC_KEY_LENGTH) && isUint8Array(enc.ciphertext) && enc.ciphertext.length > 0 && isUint8Array(enc.mac) && enc.mac.length === MAC.LENGTH;
}
function serializeECIES(encrypted) {
const combined = new Uint8Array(
encrypted.iv.length + encrypted.ephemPublicKey.length + encrypted.ciphertext.length + encrypted.mac.length
);
let offset = 0;
combined.set(encrypted.iv, offset);
offset += encrypted.iv.length;
combined.set(encrypted.ephemPublicKey, offset);
offset += encrypted.ephemPublicKey.length;
combined.set(encrypted.ciphertext, offset);
offset += encrypted.ciphertext.length;
combined.set(encrypted.mac, offset);
return toHex(combined).slice(2);
}
function deserializeECIES(hex) {
const hexWithPrefix = hex.startsWith("0x") ? hex : `0x${hex}`;
const bytes = fromHex(hexWithPrefix, "bytes");
const absoluteMinLength = FORMAT.IV_LENGTH + 1 + MAC.LENGTH + 1;
if (bytes.length < absoluteMinLength) {
throw new ECIESError(
`Invalid ECIES data: too short (${bytes.length} bytes, minimum ${absoluteMinLength} bytes required)`,
"DECRYPTION_FAILED"
);
}
const prefix = bytes[FORMAT.EPHEMERAL_KEY_OFFSET];
if (prefix !== CURVE.PREFIX.UNCOMPRESSED) {
throw new ECIESError(
`Invalid ephemeral public key: must be uncompressed format (0x04 prefix), got 0x${prefix.toString(16).padStart(2, "0")}`,
"DECRYPTION_FAILED"
);
}
const ephemKeySize = CURVE.UNCOMPRESSED_PUBLIC_KEY_LENGTH;
const minLength = FORMAT.IV_LENGTH + ephemKeySize + MAC.LENGTH + 1;
if (bytes.length < minLength) {
throw new ECIESError(
`Invalid ECIES data: too short (${bytes.length} bytes, minimum ${minLength} bytes required)`,
"DECRYPTION_FAILED"
);
}
return {
iv: bytes.subarray(FORMAT.IV_OFFSET, FORMAT.IV_OFFSET + FORMAT.IV_LENGTH),
ephemPublicKey: bytes.subarray(
FORMAT.EPHEMERAL_KEY_OFFSET,
FORMAT.EPHEMERAL_KEY_OFFSET + ephemKeySize
),
ciphertext: bytes.subarray(
FORMAT.EPHEMERAL_KEY_OFFSET + ephemKeySize,
bytes.length - MAC.LENGTH
),
mac: bytes.subarray(bytes.length - MAC.LENGTH)
};
}
export {
ECIESError,
deserializeECIES,
isECIESEncrypted,
serializeECIES
};
//# sourceMappingURL=interface.js.map