@didtools/cacao
Version:
Typescript library for Ceramic OCAP
208 lines (207 loc) • 7.17 kB
JavaScript
// @ts-nocheck
import * as dagCbor from '@ipld/dag-cbor';
import * as Block from 'multiformats/block';
import { sha256 as hasher } from 'multiformats/hashes/sha2';
// 5 minute default clockskew
const CLOCK_SKEW_DEFAULT_SEC = 5 * 60;
// CACAOs issued after that day must be of new format
export const LEGACY_CHAIN_ID_REORG_DATE = new Date('2022-09-20').valueOf();
export var Cacao;
(function(Cacao) {
function fromSiweMessage(siweMessage) {
const cacao = {
h: {
t: 'eip4361'
},
p: {
domain: siweMessage.domain,
iat: siweMessage.issuedAt,
iss: `did:pkh:eip155:${siweMessage.chainId}:${siweMessage.address}`,
aud: siweMessage.uri,
version: siweMessage.version,
nonce: siweMessage.nonce
}
};
if (siweMessage.signature) {
cacao.s = {
t: 'eip191',
s: siweMessage.signature
};
}
if (siweMessage.notBefore) {
cacao.p.nbf = siweMessage.notBefore;
}
if (siweMessage.expirationTime) {
cacao.p.exp = siweMessage.expirationTime;
}
if (siweMessage.statement) {
cacao.p.statement = siweMessage.statement;
}
if (siweMessage.requestId) {
cacao.p.requestId = siweMessage.requestId;
}
if (siweMessage.resources) {
cacao.p.resources = siweMessage.resources;
}
return cacao;
}
Cacao.fromSiweMessage = fromSiweMessage;
function fromSiwsMessage(siwsMessage) {
const cacao = {
h: {
t: 'caip122'
},
p: {
domain: siwsMessage.domain,
iat: siwsMessage.issuedAt,
iss: `did:pkh:solana:${siwsMessage.chainId}:${siwsMessage.address}`,
aud: siwsMessage.uri,
version: siwsMessage.version,
nonce: siwsMessage.nonce
}
};
if (siwsMessage.signature) {
cacao.s = {
// https://github.com/solana-labs/wallet-adapter/issues/179
t: 'solana:ed25519',
s: siwsMessage.signature
};
}
if (siwsMessage.notBefore) {
cacao.p.nbf = siwsMessage.notBefore;
}
if (siwsMessage.expirationTime) {
cacao.p.exp = siwsMessage.expirationTime;
}
if (siwsMessage.statement) {
cacao.p.statement = siwsMessage.statement;
}
if (siwsMessage.requestId) {
cacao.p.requestId = siwsMessage.requestId;
}
if (siwsMessage.resources) {
cacao.p.resources = siwsMessage.resources;
}
return cacao;
}
Cacao.fromSiwsMessage = fromSiwsMessage;
function fromSiwTezosMessage(siwTezosMessage) {
const cacao = {
h: {
t: 'caip122'
},
p: {
domain: siwTezosMessage.domain,
iat: siwTezosMessage.issuedAt,
iss: `did:pkh:tezos:${siwTezosMessage.chainId}:${siwTezosMessage.address}`,
aud: siwTezosMessage.uri,
version: siwTezosMessage.version,
nonce: siwTezosMessage.nonce
}
};
if (siwTezosMessage.signature) {
cacao.s = {
t: 'tezos:ed25519',
s: siwTezosMessage.signature
};
}
if (siwTezosMessage.notBefore) {
cacao.p.nbf = siwTezosMessage.notBefore;
}
if (siwTezosMessage.expirationTime) {
cacao.p.exp = siwTezosMessage.expirationTime;
}
if (siwTezosMessage.statement) {
cacao.p.statement = siwTezosMessage.statement;
}
if (siwTezosMessage.requestId) {
cacao.p.requestId = siwTezosMessage.requestId;
}
if (siwTezosMessage.resources) {
cacao.p.resources = siwTezosMessage.resources;
}
return cacao;
}
Cacao.fromSiwTezosMessage = fromSiwTezosMessage;
function fromSiwStacksMessage(siwStacksMessage) {
const cacao = {
h: {
t: 'caip122'
},
p: {
domain: siwStacksMessage.domain,
iat: siwStacksMessage.issuedAt,
iss: `did:pkh:stacks:${siwStacksMessage.chainId}:${siwStacksMessage.address}`,
aud: siwStacksMessage.uri,
version: siwStacksMessage.version,
nonce: siwStacksMessage.nonce
}
};
if (siwStacksMessage.signature) {
cacao.s = {
t: 'stacks:secp256k1',
s: siwStacksMessage.signature
};
}
if (siwStacksMessage.notBefore) {
cacao.p.nbf = siwStacksMessage.notBefore;
}
if (siwStacksMessage.expirationTime) {
cacao.p.exp = siwStacksMessage.expirationTime;
}
if (siwStacksMessage.statement) {
cacao.p.statement = siwStacksMessage.statement;
}
if (siwStacksMessage.requestId) {
cacao.p.requestId = siwStacksMessage.requestId;
}
if (siwStacksMessage.resources) {
cacao.p.resources = siwStacksMessage.resources;
}
return cacao;
}
Cacao.fromSiwStacksMessage = fromSiwStacksMessage;
async function fromBlockBytes(bytes) {
const block = await Block.decode({
bytes: bytes,
codec: dagCbor,
hasher: hasher
});
return block.value;
}
Cacao.fromBlockBytes = fromBlockBytes;
async function verify(cacao, opts = {}) {
assertSigned(cacao);
const verify = opts.verifiers[cacao.s.t];
if (!verify) throw new Error('Unsupported CACAO signature type, register the needed verifier');
return verify(cacao, opts);
}
Cacao.verify = verify;
})(Cacao || (Cacao = {}));
export var CacaoBlock;
(function(CacaoBlock) {
function fromCacao(cacao) {
return Block.encode({
value: cacao,
codec: dagCbor,
hasher: hasher
});
}
CacaoBlock.fromCacao = fromCacao;
})(CacaoBlock || (CacaoBlock = {}));
export function assertSigned(cacao) {
if (cacao.s === null || cacao.s === undefined) {
throw new Error(`CACAO does not have a signature`);
}
}
export function verifyTimeChecks(cacao, options) {
const atTime = options.atTime ? options.atTime.getTime() : Date.now();
const clockSkew = (options.clockSkewSecs ?? CLOCK_SKEW_DEFAULT_SEC) * 1000;
if (Date.parse(cacao.p.iat) > atTime + clockSkew || Date.parse(cacao.p.nbf) > atTime + clockSkew) {
throw new Error(`CACAO is not valid yet`);
}
const phaseOutMS = options.revocationPhaseOutSecs ? options.revocationPhaseOutSecs * 1000 : 0;
if (!options.disableExpirationCheck && Date.parse(cacao.p.exp) + phaseOutMS + clockSkew < atTime) {
throw new Error(`CACAO has expired`);
}
}