@iden3/js-iden3-core
Version:
Low level API to create and manipulate iden3 Claims.
194 lines (193 loc) • 7.31 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.DID = void 0;
const id_1 = require("../id");
const constants_1 = require("../constants");
const elemBytes_1 = require("../elemBytes");
const did_helper_1 = require("./did-helper");
const did_parser_1 = require("./did-parser");
const js_crypto_1 = require("@iden3/js-crypto");
const utils_1 = require("../utils");
// DID Decentralized Identifiers (DIDs)
// https://w3c.github.io/did-core/#did-syntax
class DID {
constructor(d) {
this.method = '';
this.id = '';
this.idStrings = [];
this.params = [];
this.path = '';
this.pathSegments = [];
this.query = '';
this.fragment = '';
if (d) {
Object.assign(this, d);
}
}
isUrl() {
return (this.params.length > 0 ||
!!this.path ||
this.pathSegments.length > 0 ||
!!this.query ||
!!this.fragment);
}
string() {
const buff = ['did:'];
if (this.method) {
buff.push(`${this.method}:`);
}
else {
return '';
}
if (this.id) {
buff.push(this.id);
}
else if (this.idStrings.length) {
buff.push(this.idStrings.join(':'));
}
else {
return '';
}
if (this.params.length) {
for (const param of this.params) {
const p = param.toString();
if (p) {
buff.push(`;${p}`);
}
else {
return '';
}
}
}
if (this.path) {
buff.push(`/${this.path}`);
}
else if (this.pathSegments.length) {
buff.push(`/${this.pathSegments.join('/')}`);
}
if (this.query) {
buff.push(`?${this.query}`);
}
if (this.fragment) {
buff.push(`#${this.fragment}`);
}
return buff.join('');
}
toJSON() {
return this.string();
}
static parse(s) {
const parser = new did_parser_1.Parser(s);
let parserState = parser.checkLength();
while (parserState) {
parserState = parserState();
}
parser.out.id = parser.out.idStrings.join(':');
parser.out.path = parser.out.pathSegments.join('/');
return new DID(parser.out);
}
static decodePartsFromId(id) {
const method = (0, did_helper_1.findDIDMethodByValue)(id.bytes[0]);
const blockchain = (0, did_helper_1.findBlockchainForDIDMethodByValue)(method, id.bytes[1]);
const networkId = (0, did_helper_1.findNetworkIDForDIDMethodByValue)(method, id.bytes[1]);
return { method, blockchain, networkId };
}
static networkIdFromId(id) {
return DID.throwIfDIDUnsupported(id).networkId;
}
static methodFromId(id) {
return DID.throwIfDIDUnsupported(id).method;
}
static blockchainFromId(id) {
return DID.throwIfDIDUnsupported(id).blockchain;
}
static throwIfDIDUnsupported(id) {
const { method, blockchain, networkId } = DID.decodePartsFromId(id);
if (DID.isUnsupported(method, blockchain, networkId)) {
throw new Error(`${constants_1.Constants.ERRORS.UNKNOWN_DID_METHOD.message}: unsupported DID`);
}
return { method, blockchain, networkId };
}
// DIDGenesisFromIdenState calculates the genesis ID from an Identity State and returns it as DID
static newFromIdenState(typ, state) {
const id = id_1.Id.idGenesisFromIdenState(typ, state);
return DID.parseFromId(id);
}
// NewDID creates a new *w3c.DID from the type and the genesis
static new(typ, genesis) {
return DID.parseFromId(new id_1.Id(typ, genesis));
}
// ParseDIDFromID returns DID from ID
static parseFromId(id) {
if (!elemBytes_1.BytesHelper.checkChecksum(id.bytes)) {
throw new Error(`${constants_1.Constants.ERRORS.UNSUPPORTED_ID.message}: invalid checksum`);
}
const { method, blockchain, networkId } = DID.throwIfDIDUnsupported(id);
const didParts = [constants_1.Constants.DID.DID_SCHEMA, method.toString(), blockchain.toString()];
if (networkId) {
didParts.push(networkId.toString());
}
didParts.push(id.string());
const didString = didParts.join(':');
const did = DID.parse(didString);
return did;
}
static idFromDID(did) {
let id;
try {
id = DID.getIdFromDID(did);
}
catch (error) {
if (error.message === constants_1.Constants.ERRORS.UNKNOWN_DID_METHOD.message) {
return DID.idFromUnsupportedDID(did);
}
throw error;
}
return id;
}
static isUnsupported(method, blockchain, networkId) {
return (method == constants_1.DidMethod.Other &&
blockchain == constants_1.Blockchain.Unknown &&
networkId == constants_1.NetworkId.Unknown);
}
static idFromUnsupportedDID(did) {
const hash = (0, js_crypto_1.sha256)(utils_1.encoder.encode(did.string()));
const genesis = new Uint8Array(27);
const idSlice = hash.slice(hash.length - constants_1.Constants.GENESIS_LENGTH);
for (let i = 0; i < genesis.length; i++) {
genesis[i] = idSlice[i] ?? 0;
}
const flg = new did_helper_1.DIDNetworkFlag(constants_1.Blockchain.Unknown, constants_1.NetworkId.Unknown);
const tp = Uint8Array.from([
constants_1.DidMethodByte[constants_1.DidMethod.Other],
constants_1.DidMethodNetwork[constants_1.DidMethod.Other][flg.toString()]
]);
return new id_1.Id(tp, genesis);
}
static getIdFromDID(did) {
const method = did.method;
const methodByte = constants_1.DidMethodByte[method];
if (!methodByte || method === constants_1.DidMethod.Other) {
throw constants_1.Constants.ERRORS.UNKNOWN_DID_METHOD;
}
if (did.idStrings.length > 3 || did.idStrings.length < 2) {
throw new Error(`${constants_1.Constants.ERRORS.INCORRECT_DID}: unexpected number of ID strings`);
}
const id = id_1.Id.fromString(did.idStrings[did.idStrings.length - 1]);
if (!elemBytes_1.BytesHelper.checkChecksum(id.bytes)) {
throw new Error(`${constants_1.Constants.ERRORS.INCORRECT_DID}: incorrect ID checksum`);
}
const { method: method2, blockchain, networkId } = DID.decodePartsFromId(id);
if (method2.toString() !== method.toString()) {
throw new Error(`${constants_1.Constants.ERRORS.INCORRECT_DID}: methods in Id and DID are different`);
}
if (blockchain.toString() !== did.idStrings[0]) {
throw new Error(`${constants_1.Constants.ERRORS.INCORRECT_DID}: blockchains in ID and DID are different`);
}
if (did.idStrings.length > 2 && networkId.toString() != did.idStrings[1]) {
throw new Error(`${constants_1.Constants.ERRORS.INCORRECT_DID}: networkIDs in Id and DID are different`);
}
return id;
}
}
exports.DID = DID;