@arcblock/did
Version:
Javascript lib to work with ArcBlock DID
146 lines (145 loc) • 6.68 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.DID_TYPE_PASSKEY = exports.DID_TYPE_ETHEREUM = exports.DID_TYPE_ARCBLOCK = exports.DID_PREFIX = exports.DidType = exports.fromTypeInfo = exports.toTypeInfoStr = exports.toTypeInfo = exports.isEthereumType = exports.isEthereumDid = exports.isValid = exports.isFromPublicKey = exports.toDid = exports.toAddress = exports.fromHash = exports.fromPublicKeyHash = exports.fromPublicKey = exports.fromSecretKey = exports.toStrictHex = exports.types = void 0;
/* eslint-disable @typescript-eslint/no-use-before-define */
/* eslint-disable @typescript-eslint/ban-ts-comment */
const mcrypto_1 = require("@ocap/mcrypto");
Object.defineProperty(exports, "types", { enumerable: true, get: function () { return mcrypto_1.types; } });
const util_1 = require("@ocap/util");
Object.defineProperty(exports, "toAddress", { enumerable: true, get: function () { return util_1.toAddress; } });
Object.defineProperty(exports, "toDid", { enumerable: true, get: function () { return util_1.toDid; } });
const type_1 = require("./type");
Object.defineProperty(exports, "DidType", { enumerable: true, get: function () { return type_1.DidType; } });
Object.defineProperty(exports, "DID_TYPE_ARCBLOCK", { enumerable: true, get: function () { return type_1.DID_TYPE_ARCBLOCK; } });
Object.defineProperty(exports, "DID_TYPE_ETHEREUM", { enumerable: true, get: function () { return type_1.DID_TYPE_ETHEREUM; } });
Object.defineProperty(exports, "DID_TYPE_PASSKEY", { enumerable: true, get: function () { return type_1.DID_TYPE_PASSKEY; } });
Object.defineProperty(exports, "fromTypeInfo", { enumerable: true, get: function () { return type_1.fromTypeInfo; } });
Object.defineProperty(exports, "isEthereumDid", { enumerable: true, get: function () { return type_1.isEthereumDid; } });
Object.defineProperty(exports, "isEthereumType", { enumerable: true, get: function () { return type_1.isEthereumType; } });
Object.defineProperty(exports, "toTypeInfo", { enumerable: true, get: function () { return type_1.toTypeInfo; } });
Object.defineProperty(exports, "toTypeInfoStr", { enumerable: true, get: function () { return type_1.toTypeInfoStr; } });
const util_2 = require("./util");
Object.defineProperty(exports, "DID_PREFIX", { enumerable: true, get: function () { return util_2.DID_PREFIX; } });
Object.defineProperty(exports, "toStrictHex", { enumerable: true, get: function () { return util_2.toStrictHex; } });
/**
* Gen DID from private key and type config
*
* Spec: https://github.com/ArcBlock/ABT-DID-Protocol#create-did
*
* @public
* @static
* @param {string} sk - hex encoded secret key string
* @param {object} type - wallet type, {@see @ocap/wallet#WalletType}
* @returns {string} DID string
*/
const fromSecretKey = (sk, type) => {
const info = (0, type_1.DidType)(type);
const pub = (0, mcrypto_1.getSigner)(info.pk).getPublicKey(sk);
return fromPublicKey(pub.indexOf('0x') === 0 ? pub : `0x${pub}`, info);
};
exports.fromSecretKey = fromSecretKey;
/**
* Gen DID from public key and type config
*
* @public
* @static
* @param {string} pk - hex encoded public key
* @param {object} type - wallet type, {@see @ocap/wallet#WalletType}
* @returns {string} DID string
*/
const fromPublicKey = (pk, type) => {
const info = (0, type_1.DidType)(type);
const hashFn = (0, mcrypto_1.getHasher)(info.hash);
const pkHash = hashFn(pk, 1);
return fromPublicKeyHash(pkHash, info);
};
exports.fromPublicKey = fromPublicKey;
const fromPublicKeyHash = (buffer, type) => {
const info = (0, type_1.DidType)(type);
const pkHash = (0, util_1.stripHexPrefix)(buffer).slice(0, 40); // 20 bytes
const hashFn = (0, mcrypto_1.getHasher)(info.hash);
const typeHex = (0, type_1.fromTypeInfo)(info);
const checksum = (0, util_1.stripHexPrefix)(hashFn(`0x${typeHex}${pkHash}`, 1)).slice(0, 8); // 4 bytes
const didHash = `0x${typeHex}${pkHash}${checksum}`;
// ethereum-compatible address, this address does not contain any type info
// but we can infer from the address itself
if ((0, type_1.isEthereumType)(info)) {
return (0, type_1.toChecksumAddress)(`0x${buffer.slice(-40)}`);
}
// default forge-compatible did
if (info.address === mcrypto_1.types.EncodingType.BASE58) {
return (0, util_1.toBase58)(didHash);
}
// fallback base16 encoding
return didHash;
};
exports.fromPublicKeyHash = fromPublicKeyHash;
/**
* Gen DID from an hex encoded hash and role type
*
* @public
* @static
* @param {string} hash - hex encoded hash
* @param {enum} role - role type, {@see @ocap/mcrypto#types}
* @returns {string} DID string
*/
const fromHash = (hash, role = mcrypto_1.types.RoleType.ROLE_ACCOUNT) => {
const roleKeys = Object.keys(mcrypto_1.types.RoleType);
const roleValues = Object.values(mcrypto_1.types.RoleType);
if (roleValues.indexOf(role) === -1) {
throw new Error(`Unsupported role type ${role} when gen ddi from hash`);
}
const type = (0, type_1.DidType)({
// @ts-ignore
role: mcrypto_1.types.RoleType[roleKeys[roleValues.indexOf(role)]],
});
return fromPublicKeyHash(hash, type);
};
exports.fromHash = fromHash;
/**
* Check if an DID is generated from a publicKey
*
* @public
* @static
* @param {string} did - string of the did, usually base58btc format
* @param {string} pk - hex encoded publicKey string
* @returns {boolean}
*/
const isFromPublicKey = (did, pk) => {
if (isValid(did) === false) {
return false;
}
const type = (0, type_1.toTypeInfo)(did);
const didNew = fromPublicKey(pk, type);
const didClean = did.replace(util_2.DID_PREFIX, '');
return didNew === didClean;
};
exports.isFromPublicKey = isFromPublicKey;
/**
* Check if a DID string is valid
*
* @public
* @static
* @param {string} did - address string
* @returns {boolean}
*/
const isValid = (did) => {
if (!did) {
return false;
}
const address = (0, util_1.toAddress)(String(did));
const { hash } = (0, type_1.toTypeInfo)(address);
if (typeof hash === 'undefined') {
return false;
}
if ((0, type_1.isEthereumDid)(address)) {
return true;
}
const hashFn = (0, mcrypto_1.getHasher)(hash);
const bytes = (0, util_2.toBytes)(address);
const bytesHex = (0, util_2.toStrictHex)(Buffer.from(bytes.slice(0, 22)).toString('hex'));
const didChecksum = (0, util_2.toStrictHex)(Buffer.from(bytes.slice(22, 26)).toString('hex'));
const checksum = (0, util_1.stripHexPrefix)(hashFn(`0x${bytesHex}`, 1)).slice(0, 8);
return didChecksum === checksum;
};
exports.isValid = isValid;