@kya-os/mcp-i
Version:
The TypeScript MCP framework with identity features built-in
119 lines (118 loc) • 4.22 kB
JavaScript
;
/**
* Identity Migration Utility
*
* Migrates old identity files from keyId format to kid multibase format
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.migrateIdentityFile = migrateIdentityFile;
exports.generateMultibaseKid = generateMultibaseKid;
const promises_1 = require("fs/promises");
const fs_1 = require("fs");
/**
* Migrate an identity file from old keyId format to new kid format
* @param identityPath Path to the identity file
* @returns true if migration was performed, false if already migrated
*/
async function migrateIdentityFile(identityPath) {
if (!(0, fs_1.existsSync)(identityPath)) {
throw new Error(`Identity file not found: ${identityPath}`);
}
const content = await (0, promises_1.readFile)(identityPath, "utf-8");
const identity = JSON.parse(content);
// Check if already migrated (has kid field)
if (identity.kid) {
console.log("Identity file already migrated to kid format");
return false;
}
// Check if has old format keyId
if (!identity.keyId) {
throw new Error("Identity file has neither kid nor keyId field");
}
// Check if it's the old format (key-[hex])
if (identity.keyId.startsWith('key-')) {
// Generate multibase kid from public key
const kid = generateMultibaseKid(identity.publicKey);
// Create migrated identity
const migratedIdentity = {
version: identity.version || "1.0",
did: identity.did,
kid, // New field
privateKey: identity.privateKey,
publicKey: identity.publicKey,
createdAt: identity.createdAt,
lastRotated: identity.lastRotated || new Date().toISOString(),
};
// Save migrated identity
await (0, promises_1.writeFile)(identityPath, JSON.stringify(migratedIdentity, null, 2), {
mode: 0o600,
});
console.log(`✅ Migrated identity file to new multibase kid format`);
console.log(` Old keyId: ${identity.keyId}`);
console.log(` New kid: ${kid}`);
return true;
}
// Already in multibase format, just rename field
const renamedIdentity = {
version: identity.version || "1.0",
did: identity.did,
kid: identity.keyId, // Rename field from keyId to kid
privateKey: identity.privateKey,
publicKey: identity.publicKey,
createdAt: identity.createdAt,
lastRotated: identity.lastRotated,
};
await (0, promises_1.writeFile)(identityPath, JSON.stringify(renamedIdentity, null, 2), {
mode: 0o600,
});
console.log(`✅ Renamed keyId field to kid`);
return true;
}
/**
* Generate multibase-encoded key identifier (z-prefix base58btc)
*/
function generateMultibaseKid(base64PublicKey) {
const publicKeyBytes = Buffer.from(base64PublicKey, "base64");
// Ed25519 public key prefix (0xed01) + key bytes
const prefixedKey = Buffer.concat([
Buffer.from([0xed, 0x01]), // Ed25519 multicodec prefix
publicKeyBytes,
]);
// Convert to base58btc
const base58 = encodeBase58(prefixedKey);
return `z${base58}`; // 'z' prefix indicates base58btc
}
/**
* Simple base58 encoding
*/
function encodeBase58(buffer) {
const alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
let num = BigInt("0x" + buffer.toString("hex"));
let result = "";
while (num > 0n) {
const remainder = num % 58n;
result = alphabet[Number(remainder)] + result;
num = num / 58n;
}
// Handle leading zeros
for (let i = 0; i < buffer.length && buffer[i] === 0; i++) {
result = "1" + result;
}
return result;
}
// CLI usage
if (require.main === module) {
const args = process.argv.slice(2);
if (args.length !== 1) {
console.error("Usage: ts-node migrate-identity.ts <path-to-identity.json>");
process.exit(1);
}
migrateIdentityFile(args[0])
.then((migrated) => {
process.exit(migrated ? 0 : 1);
})
.catch((error) => {
console.error("Migration failed:", error.message);
process.exit(1);
});
}