Skip to content

Commit

Permalink
chore: linting
Browse files Browse the repository at this point in the history
  • Loading branch information
rflechtner committed Oct 23, 2023
1 parent ec56b7a commit be7811c
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 91 deletions.
58 changes: 29 additions & 29 deletions packages/did/src/Did.chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,35 @@ export async function getStoreTxFromDidDocument(
return getStoreTxFromInput(storeTxInput, submitter, sign)
}

/**
* Compiles an enum-type key-value pair representation of a signature created with a signer associated with a full DID verification method. Required for creating full DID signed extrinsics.
*
* @param input Signature and algorithm.
* @param input.algorithm Descriptor of the signature algorithm used by the signer.
* @param input.signature The signature generated by the signer.
* @returns Data restructured to allow SCALE encoding by polkadot api.
*/
export function didSignatureToChain({
algorithm,
signature,
}: {
algorithm: string
signature: Uint8Array
}): EncodedSignature {
const lower = algorithm.toLowerCase()
const keyType =
lower === Signers.ALGORITHMS.ECRECOVER_SECP256K1_BLAKE2B.toLowerCase()
? 'ecdsa'
: lower
if (!isValidVerificationMethodType(keyType)) {
throw new SDKErrors.DidError(
`encodedDidSignature requires a verification key. A key of type "${keyType}" was used instead`
)
}

return { [keyType]: signature } as EncodedSignature
}

export interface SigningOptions {
signer: SignerInterface
}
Expand Down Expand Up @@ -581,32 +610,3 @@ export async function generateDidAuthenticatedTx({
})
return api.tx.did.submitDidCall(signableCall, encodedSignature)
}

/**
* Compiles an enum-type key-value pair representation of a signature created with a signer associated with a full DID verification method. Required for creating full DID signed extrinsics.
*
* @param input Signature and algorithm.
* @param input.algorithm Descriptor of the signature algorithm used by the signer.
* @param input.signature The signature generated by the signer.
* @returns Data restructured to allow SCALE encoding by polkadot api.
*/
export function didSignatureToChain({
algorithm,
signature,
}: {
algorithm: string
signature: Uint8Array
}): EncodedSignature {
const lower = algorithm.toLowerCase()
const keyType =
lower === Signers.ALGORITHMS.ECRECOVER_SECP256K1_BLAKE2B.toLowerCase()
? 'ecdsa'
: lower
if (!isValidVerificationMethodType(keyType)) {
throw new SDKErrors.DidError(
`encodedDidSignature requires a verification key. A key of type "${keyType}" was used instead`
)
}

return { [keyType]: signature } as EncodedSignature
}
2 changes: 0 additions & 2 deletions packages/did/src/Did.signature.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,6 @@ describe('light DID', () => {
const signature = await authenticationSigner.sign({
data: Crypto.coToUInt8(SIGNED_STRING),
})
// @ts-expect-error
const keyUri = authenticationSigner.id.replace('#', '?')
await expect(
verifyDidSignature({
message: SIGNED_STRING,
Expand Down
12 changes: 6 additions & 6 deletions packages/legacy-credentials/src/Credential.ts
Original file line number Diff line number Diff line change
Expand Up @@ -548,23 +548,23 @@ export async function createPresentation({
excludedClaimProperties
)

if (!didDocument) {
didDocument = (await resolve(credential.claim.owner)).didDocument
}
if (!didDocument) {
const didDoc =
didDocument ?? (await resolve(credential.claim.owner)).didDocument

if (!didDoc) {
throw new Error(
`Unable to sign: Failed to resolve claimer DID ${credential.claim.owner}`
)
}
const signer = await Signers.selectSigner(
signers,
verifiableOnChain(),
byDid(didDocument, { verificationRelationship: 'authentication' })
byDid(didDoc, { verificationRelationship: 'authentication' })
)
if (!signer) {
throw new SDKErrors.NoSuitableSignerError(undefined, {
signerRequirements: {
did: didDocument.id,
did: didDoc.id,
algorithm: Signers.DID_PALLET_SUPPORTED_ALGORITHMS,
verificationRelationship: 'authentication',
},
Expand Down
1 change: 0 additions & 1 deletion packages/types/src/Imported.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,3 @@ export type { HexString } from '@polkadot/util/types'
export type { Prefix } from '@polkadot/util-crypto/address/types'
export type { SubmittableExtrinsic } from '@polkadot/api/promise/types'
export type { KeyringPair } from '@polkadot/keyring/types'
export type { SignerInterface } from '@kiltprotocol/jcs-data-integrity-proofs-common'
12 changes: 12 additions & 0 deletions packages/types/src/Signers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* Copyright (c) 2018-2023, BOTLabs GmbH.
*
* This source code is licensed under the BSD 4-Clause "Original" license
* found in the LICENSE file in the root directory of this source tree.
*/

export type SignerInterface = {
algorithm: string
id: string
sign: (input: { data: Uint8Array }) => Promise<Uint8Array>
}
1 change: 1 addition & 0 deletions packages/types/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ export * from './CryptoCallbacks.js'
export * from './DidResolver.js'
export * from './PublicCredential.js'
export * from './Imported.js'
export * from './Signers.js'
138 changes: 85 additions & 53 deletions packages/utils/src/Signers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,19 @@ export const DID_PALLET_SUPPORTED_ALGORITHMS = Object.freeze([
* Signer that produces an ECDSA signature over a Blake2b-256 digest of the message using the secp256k1 curve.
* The signature has a recovery bit appended to the end, allowing public key recovery.
*
* @param root0
* @param root0.keyUri
* @param root0.publicKey
* @param root0.secretKey
* @param input Holds all function arguments.
* @param input.keyUri Sets the signer's id property.
* @param input.secretKey A 32 byte ECDSA secret key on the secp256k1 curve.
* @param input.publicKey The corresponding public key. May be omitted.
* @returns A signer interface capable of making ECDSA signatures with recovery bit added.
*/
export async function polkadotEcdsaSigner({
secretKey,
keyUri,
keyUri, // TODO: I think this should just be called id
}: {
publicKey?: Uint8Array
secretKey: Uint8Array
keyUri: string
secretKey: Uint8Array
publicKey?: Uint8Array
}): Promise<SignerInterface> {
return {
id: keyUri,
Expand All @@ -79,19 +80,19 @@ export async function polkadotEcdsaSigner({
* Signer that produces an ECDSA signature over a Keccak-256 digest of the message using the secp256k1 curve.
* The signature has a recovery bit appended to the end, allowing public key recovery.
*
* @param input
* @param input.keyUri
* @param input.publicKey
* @param input.secretKey
* @returns
* @param input Holds all function arguments.
* @param input.keyUri Sets the signer's id property.
* @param input.secretKey A 32 byte ECDSA secret key on the secp256k1 curve.
* @param input.publicKey The corresponding public key. May be omitted.
* @returns A signer interface capable of making ECDSA signatures with recovery bit added.
*/
export async function ethereumEcdsaSigner({
secretKey,
keyUri,
}: {
publicKey?: Uint8Array
secretKey: Uint8Array
keyUri: string
secretKey: Uint8Array
publicKey?: Uint8Array
}): Promise<SignerInterface> {
return {
id: keyUri,
Expand All @@ -105,19 +106,19 @@ export async function ethereumEcdsaSigner({
/**
* Signer that produces an ES256K signature over the message.
*
* @param input
* @param input.keyUri
* @param input.publicKey
* @param input.secretKey
* @returns
* @param input Holds all function arguments.
* @param input.keyUri Sets the signer's id property.
* @param input.secretKey A 32 byte ECDSA secret key on the secp256k1 curve.
* @param input.publicKey The corresponding public key. May be omitted.
* @returns A signer interface capable of making ES256K signatures.
*/
export async function es256kSigner({
secretKey,
keyUri,
}: {
publicKey?: Uint8Array
secretKey: Uint8Array
keyUri: string
secretKey: Uint8Array
publicKey?: Uint8Array
}): Promise<SignerInterface> {
// only exists to map secretKey to seed
return es256kSignerWrapped({ seed: secretKey, keyUri })
Expand All @@ -126,19 +127,19 @@ export async function es256kSigner({
/**
* Signer that produces an Ed25519 signature over the message.
*
* @param input
* @param input.keyUri
* @param input.publicKey
* @param input.secretKey
* @returns
* @param input Holds all function arguments.
* @param input.keyUri Sets the signer's id property.
* @param input.secretKey A 32 byte Ed25519 secret key. Some key representations append the public key to the private key; to allow these, all bytes after the 32nd byte will be dropped.
* @param input.publicKey The corresponding public key. May be omitted.
* @returns A signer interface capable of making Ed25519 signatures.
*/
export async function ed25519Signer({
secretKey,
keyUri,
}: {
publicKey?: Uint8Array
secretKey: Uint8Array
keyUri: string
secretKey: Uint8Array
publicKey?: Uint8Array
}): Promise<SignerInterface> {
// polkadot ed25519 private keys are a concatenation of private and public key for some reason
return ed25519SignerWrapped({ seed: secretKey.slice(0, 32), keyUri })
Expand All @@ -147,11 +148,11 @@ export async function ed25519Signer({
/**
* Signer that produces an Sr25519 signature over the message.
*
* @param input
* @param input.keyUri
* @param input.publicKey
* @param input.secretKey
* @returns
* @param input Holds all function arguments.
* @param input.keyUri Sets the signer's id property.
* @param input.secretKey A 64 byte Sr25519 secret key.
* @param input.publicKey The corresponding 32 byte public key.
* @returns A signer interface capable of making Sr25519 signatures.
*/
export async function sr25519Signer({
secretKey,
Expand Down Expand Up @@ -188,14 +189,17 @@ const signerFactory = {
}

/**
* @param root0
* @param root0.keypair
* @param root0.algorithm
* @param root0.keyUri
* Creates a signer interface based on an existing keypair and an algorithm descriptor.
*
* @param input Holds all function arguments.
* @param input.keyUri Sets the signer's id property.
* @param input.keypair A polkadot {@link KeyringPair} or combination of `secretKey` & `publicKey`.
* @param input.algorithm An algorithm identifier from the {@link ALGORITHMS} map.
* @returns A signer interface.
*/
export async function signerFromKeypair({
keypair,
keyUri,
keypair,
algorithm,
}: {
keypair: Keypair | KeyringPair
Expand Down Expand Up @@ -256,19 +260,22 @@ function algsForKeyType(keyType: string): string[] {
}

/**
* @param root0
* @param root0.keypair
* @param root0.type
* @param root0.keyUri
* Based on an existing keypair and its type, creates all available signers that work with this key type.
*
* @param input Holds all function arguments.
* @param input.keyUri Sets the signer's id property.
* @param input.keypair A polkadot {@link KeyringPair} or combination of `secretKey` & `publicKey`.
* @param input.type If `keypair` is not a {@link KeyringPair}, provide the key type here; otherwise, this is ignored.
* @returns An array of signer interfaces based on the keypair and type.
*/
export async function getSignersForKeypair({
keyUri,
keypair,
type = (keypair as KeyringPair).type,
keyUri,
}: {
keyUri?: string
keypair: Keypair | KeyringPair
type?: string
keyUri?: string
}): Promise<SignerInterface[]> {
if (!type) {
throw new Error('type is required if keypair.type is not given')
Expand All @@ -282,12 +289,15 @@ export async function getSignersForKeypair({
}

export interface SignerSelector {
(signer: SignerInterface): boolean
(signer: SignerInterface): boolean // TODO: allow async
}

/**
* @param signers
* @param selectors
* Filters signer interfaces, returning only those accepted by all selectors.
*
* @param signers An array of signer interfaces.
* @param selectors One or more selector callbacks, receiving a signer as input and returning `true` in case it meets selection criteria.
* @returns An array of those signers for which all selectors returned `true`.
*/
export async function selectSigners(
signers: readonly SignerInterface[],
Expand All @@ -299,8 +309,11 @@ export async function selectSigners(
}

/**
* @param signers
* @param selectors
* Finds a suiteable signer interfaces in an array of signers, returning the first signer accepted by all selectors.
*
* @param signers An array of signer interfaces.
* @param selectors One or more selector callbacks, receiving a signer as input and returning `true` in case it meets selection criteria.
* @returns The first signer for which all selectors returned `true`, or `undefined` if none meet selection criteria.
*/
export async function selectSigner(
signers: readonly SignerInterface[],
Expand All @@ -311,17 +324,36 @@ export async function selectSigner(
})
}

function byId(id: string): SignerSelector {
return (signer) => signer.id === id
/**
* Select signers based on (key) ids.
*
* @param ids Allowed signer/key ids to filter for.
* @returns A selector identifying signers whose id property is in `ids`.
*/
function byId(ids: readonly string[]): SignerSelector {
return ({ id }) => ids.includes(id)
}

/**
* Select signers based on algorithm identifiers.
*
* @param algorithms Allowed algorithms to filter for.
* @returns A selector identifying signers whose algorithm property is in `algorithms`.
*/
function byAlgorithm(algorithms: readonly string[]): SignerSelector {
return (signer) =>
algorithms.some(
(algorithm) => algorithm.toLowerCase() === signer.algorithm.toLowerCase()
)
}

/**
* Select signers based on the association of key ids with a given DID.
*
* @param didDocument DidDocument of the DID, on which the signer id must be listed as a verification method.
* @param options Additional optional filter criteria.
* @param options.verificationRelationship If set, the signer id must be listed under this verification relationship on the DidDocument.
* @param options.controller If set, only verificationMethods with this controller are considered.
* @returns A selector identifying signers whose id is associated with the DidDocument.
*/
function byDid(
didDocument: DidDocument,
{
Expand Down

0 comments on commit be7811c

Please sign in to comment.