@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
JavaScript
/**
* 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() });
});
}