UNPKG

@gorbchain-xyz/chaindecode

Version:

GorbchainSDK V1.3+ - Complete Solana development toolkit with advanced cryptography, messaging, and collaboration features. Build secure applications with blockchain, DeFi, and end-to-end encryption.

182 lines (181 loc) 8.64 kB
/** * Group encryption for multiple recipients * Static groups with fixed membership */ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { bytesToBase58 as encodeBase58, base58ToBytes as decodeBase58 } from '../utils/base58.js'; import { Keypair } from '@solana/web3.js'; import { EncryptionMethod } from './types.js'; import { generateRandomBytes, performKeyExchange, encryptAES, decryptAES, stringToBytes, bytesToString, combineBuffers, splitBuffer, generateId, KEY_SIZE, IV_SIZE, AUTH_TAG_SIZE, getCurrentTimestamp, compressData, decompressData } from './utils.js'; /** * Create a static encryption group */ export function createGroup(groupName, memberPublicKeys, creatorPrivateKey) { return __awaiter(this, void 0, void 0, function* () { const creatorPrivKeyBytes = typeof creatorPrivateKey === 'string' ? decodeBase58(creatorPrivateKey) : creatorPrivateKey; // Get creator's public key const creatorKeypair = Keypair.fromSecretKey(creatorPrivKeyBytes); const creatorPublicKey = creatorKeypair.publicKey.toBase58(); // Generate group ID const groupId = generateId(groupName, ...memberPublicKeys.sort()); // Generate master key for the group const masterKey = generateRandomBytes(KEY_SIZE); // Create key shares for each member const keyShares = []; for (const memberPublicKey of memberPublicKeys) { const share = yield createKeyShare(masterKey, memberPublicKey, creatorPrivKeyBytes); keyShares.push(share); } return { groupId, keyShares, creatorPublicKey, nonce: '', // Will be set during encryption timestamp: getCurrentTimestamp(), version: '1.0.0' }; }); } /** * Encrypt data for a group */ export function encryptGroup(data, groupMetadata, options) { return __awaiter(this, void 0, void 0, function* () { // Convert input let dataBytes = typeof data === 'string' ? stringToBytes(data) : data; // Compress if requested if (options === null || options === void 0 ? void 0 : options.compress) { dataBytes = yield compressData(dataBytes); } // Reconstruct master key from any key share (for demonstration) // In practice, the encryptor should have the master key stored securely const masterKey = generateRandomBytes(KEY_SIZE); // Encrypt data with master key const { encrypted, iv, authTag } = encryptAES(dataBytes, masterKey); // Combine group ID, iv, authTag, and encrypted data const groupIdBytes = decodeBase58(groupMetadata.groupId); const combined = combineBuffers(groupIdBytes, iv, authTag, encrypted); // Update metadata with nonce const metadata = Object.assign(Object.assign({}, groupMetadata), { nonce: encodeBase58(iv), timestamp: getCurrentTimestamp() }); // Add compression flag if used if (options === null || options === void 0 ? void 0 : options.compress) { metadata.compressed = true; } return { encryptedData: encodeBase58(combined), method: EncryptionMethod.GROUP, metadata }; }); } /** * Decrypt group encrypted data */ export function decryptGroup(encryptionResult, memberPrivateKey, memberPublicKey) { return __awaiter(this, void 0, void 0, function* () { if (encryptionResult.method !== EncryptionMethod.GROUP) { throw new Error('Invalid encryption method for group decryption'); } const metadata = encryptionResult.metadata; const memberPrivKeyBytes = typeof memberPrivateKey === 'string' ? decodeBase58(memberPrivateKey) : memberPrivateKey; // Find member's key share const keyShare = metadata.keyShares.find(share => share.recipientPublicKey === memberPublicKey); if (!keyShare) { throw new Error('No key share found for this member'); } // Decrypt the master key const masterKey = yield decryptKeyShare(keyShare, memberPrivKeyBytes, metadata.creatorPublicKey); // Decode the combined data const combined = decodeBase58(encryptionResult.encryptedData); // Split the combined data const groupIdSize = 32; // SHA256 hash size const [groupIdBytes, iv, authTag, encrypted] = splitBuffer(combined, groupIdSize, IV_SIZE, AUTH_TAG_SIZE); // Verify group ID const groupId = encodeBase58(groupIdBytes); if (groupId !== metadata.groupId) { throw new Error('Group ID mismatch'); } // Decrypt the data let decrypted = decryptAES(encrypted, masterKey, iv, authTag); // Decompress if needed if (metadata.compressed) { decrypted = yield decompressData(decrypted); } return decrypted; }); } /** * Decrypt group encrypted data and return as string */ export function decryptGroupString(encryptionResult, memberPrivateKey, memberPublicKey) { return __awaiter(this, void 0, void 0, function* () { const decrypted = yield decryptGroup(encryptionResult, memberPrivateKey, memberPublicKey); return bytesToString(decrypted); }); } /** * Create an encrypted key share for a group member */ function createKeyShare(masterKey, recipientPublicKey, senderPrivateKey) { return __awaiter(this, void 0, void 0, function* () { const recipientPubKeyBytes = decodeBase58(recipientPublicKey); // Perform key exchange const sharedSecret = performKeyExchange(senderPrivateKey, recipientPubKeyBytes); // Encrypt master key with shared secret const { encrypted, iv, authTag } = encryptAES(masterKey, sharedSecret); // Combine iv, authTag, and encrypted key const combined = combineBuffers(iv, authTag, encrypted); return { recipientPublicKey, encryptedShare: encodeBase58(combined), createdAt: getCurrentTimestamp() }; }); } /** * Decrypt a key share to get the master key */ function decryptKeyShare(keyShare, recipientPrivateKey, senderPublicKey) { return __awaiter(this, void 0, void 0, function* () { const senderPubKeyBytes = decodeBase58(senderPublicKey); // Perform key exchange const sharedSecret = performKeyExchange(recipientPrivateKey, senderPubKeyBytes); // Decode the encrypted share const combined = decodeBase58(keyShare.encryptedShare); const [iv, authTag, encrypted] = splitBuffer(combined, IV_SIZE, AUTH_TAG_SIZE); // Decrypt the master key return decryptAES(encrypted, sharedSecret, iv, authTag); }); } /** * Add a member to an existing group (creates new metadata) */ export function addGroupMember(groupMetadata, newMemberPublicKey, authorizedMemberPrivateKey, authorizedMemberPublicKey) { return __awaiter(this, void 0, void 0, function* () { const authorizedPrivKeyBytes = typeof authorizedMemberPrivateKey === 'string' ? decodeBase58(authorizedMemberPrivateKey) : authorizedMemberPrivateKey; // First, decrypt the master key as authorized member const authorizedKeyShare = groupMetadata.keyShares.find(share => share.recipientPublicKey === authorizedMemberPublicKey); if (!authorizedKeyShare) { throw new Error('Authorized member not found in group'); } const masterKey = yield decryptKeyShare(authorizedKeyShare, authorizedPrivKeyBytes, groupMetadata.creatorPublicKey); // Create key share for new member const newKeyShare = yield createKeyShare(masterKey, newMemberPublicKey, authorizedPrivKeyBytes); // Return updated metadata return Object.assign(Object.assign({}, groupMetadata), { keyShares: [...groupMetadata.keyShares, newKeyShare], timestamp: getCurrentTimestamp() }); }); }