UNPKG

@arcblock/did

Version:
124 lines (123 loc) 4.43 kB
/* eslint-disable @typescript-eslint/no-use-before-define */ /* eslint-disable @typescript-eslint/ban-ts-comment */ import { types, getSigner, getHasher } from '@ocap/mcrypto'; import { stripHexPrefix, toAddress, toBase58, toDid } from '@ocap/util'; import { DidType, DID_TYPE_ARCBLOCK, DID_TYPE_ETHEREUM, DID_TYPE_PASSKEY, fromTypeInfo, isEthereumDid, isEthereumType, toChecksumAddress, toTypeInfo, toTypeInfoStr, } from './type'; import { DID_PREFIX, toBytes, toStrictHex } from './util'; /** * 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 = DidType(type); const pub = getSigner(info.pk).getPublicKey(sk); return fromPublicKey(pub.indexOf('0x') === 0 ? pub : `0x${pub}`, info); }; /** * 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 = DidType(type); const hashFn = getHasher(info.hash); const pkHash = hashFn(pk, 1); return fromPublicKeyHash(pkHash, info); }; const fromPublicKeyHash = (buffer, type) => { const info = DidType(type); const pkHash = stripHexPrefix(buffer).slice(0, 40); // 20 bytes const hashFn = getHasher(info.hash); const typeHex = fromTypeInfo(info); const checksum = 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 (isEthereumType(info)) { return toChecksumAddress(`0x${buffer.slice(-40)}`); } // default forge-compatible did if (info.address === types.EncodingType.BASE58) { return toBase58(didHash); } // fallback base16 encoding return didHash; }; /** * 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 = types.RoleType.ROLE_ACCOUNT) => { const roleKeys = Object.keys(types.RoleType); const roleValues = Object.values(types.RoleType); if (roleValues.indexOf(role) === -1) { throw new Error(`Unsupported role type ${role} when gen ddi from hash`); } const type = DidType({ // @ts-ignore role: types.RoleType[roleKeys[roleValues.indexOf(role)]], }); return fromPublicKeyHash(hash, type); }; /** * 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 = toTypeInfo(did); const didNew = fromPublicKey(pk, type); const didClean = did.replace(DID_PREFIX, ''); return didNew === didClean; }; /** * 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 = toAddress(String(did)); const { hash } = toTypeInfo(address); if (typeof hash === 'undefined') { return false; } if (isEthereumDid(address)) { return true; } const hashFn = getHasher(hash); const bytes = toBytes(address); const bytesHex = toStrictHex(Buffer.from(bytes.slice(0, 22)).toString('hex')); const didChecksum = toStrictHex(Buffer.from(bytes.slice(22, 26)).toString('hex')); const checksum = stripHexPrefix(hashFn(`0x${bytesHex}`, 1)).slice(0, 8); return didChecksum === checksum; }; export { types, toStrictHex, fromSecretKey, fromPublicKey, fromPublicKeyHash, fromHash, toAddress, toDid, isFromPublicKey, isValid, isEthereumDid, isEthereumType, toTypeInfo, toTypeInfoStr, fromTypeInfo, DidType, DID_PREFIX, DID_TYPE_ARCBLOCK, DID_TYPE_ETHEREUM, DID_TYPE_PASSKEY, };