Skip to content

Commit

Permalink
refactor(crypto): remove circular dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
matthieusieben committed Dec 8, 2023
1 parent 842e183 commit 9917a4f
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 28 deletions.
26 changes: 8 additions & 18 deletions packages/crypto/src/did.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,23 @@
import * as uint8arrays from 'uint8arrays'
import * as p256 from './p256/encoding'
import * as secp from './secp256k1/encoding'
import plugins from './plugins'

import {
BASE58_MULTIBASE_PREFIX,
DID_KEY_PREFIX,
P256_JWT_ALG,
SECP256K1_JWT_ALG,
} from './const'
import * as p256 from './p256/encoding'
import plugins from './plugins'
import * as secp from './secp256k1/encoding'
import { extractMultikey, extractPrefixedBytes, hasPrefix } from './utils'

export type ParsedMultikey = {
jwtAlg: string
keyBytes: Uint8Array
}

export const parseMultikey = (multikey: string): ParsedMultikey => {
if (!multikey.startsWith(BASE58_MULTIBASE_PREFIX)) {
throw new Error(`Incorrect prefix for multikey: ${multikey}`)
}
const prefixedBytes = uint8arrays.fromString(
multikey.slice(BASE58_MULTIBASE_PREFIX.length),
'base58btc',
)
const prefixedBytes = extractPrefixedBytes(multikey)
const plugin = plugins.find((p) => hasPrefix(prefixedBytes, p.prefix))
if (!plugin) {
throw new Error('Unsupported key type')
Expand Down Expand Up @@ -58,16 +54,10 @@ export const formatMultikey = (
}

export const parseDidKey = (did: string): ParsedMultikey => {
if (!did.startsWith(DID_KEY_PREFIX)) {
throw new Error(`Incorrect prefix for did:key: ${did}`)
}
return parseMultikey(did.slice(DID_KEY_PREFIX.length))
const multikey = extractMultikey(did)
return parseMultikey(multikey)
}

export const formatDidKey = (jwtAlg: string, keyBytes: Uint8Array): string => {
return DID_KEY_PREFIX + formatMultikey(jwtAlg, keyBytes)
}

const hasPrefix = (bytes: Uint8Array, prefix: Uint8Array): boolean => {
return uint8arrays.equals(prefix, bytes.subarray(0, prefix.byteLength))
}
14 changes: 8 additions & 6 deletions packages/crypto/src/p256/operations.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
import { p256 } from '@noble/curves/p256'
import { sha256 } from '@noble/hashes/sha256'
import * as ui8 from 'uint8arrays'
import { P256_JWT_ALG } from '../const'
import { parseDidKey } from '../did'
import { equals as ui8equals } from 'uint8arrays'

import { P256_DID_PREFIX } from '../const'
import { VerifyOptions } from '../types'
import { extractMultikey, extractPrefixedBytes, hasPrefix } from '../utils'

export const verifyDidSig = async (
did: string,
data: Uint8Array,
sig: Uint8Array,
opts?: VerifyOptions,
): Promise<boolean> => {
const { jwtAlg, keyBytes } = parseDidKey(did)
if (jwtAlg !== P256_JWT_ALG) {
const prefixedBytes = extractPrefixedBytes(extractMultikey(did))
if (!hasPrefix(prefixedBytes, P256_DID_PREFIX)) {
throw new Error(`Not a P-256 did:key: ${did}`)
}
const keyBytes = prefixedBytes.slice(P256_DID_PREFIX.length)
return verifySig(keyBytes, data, sig, opts)
}

Expand All @@ -39,7 +41,7 @@ export const verifySig = async (
export const isCompactFormat = (sig: Uint8Array) => {
try {
const parsed = p256.Signature.fromCompact(sig)
return ui8.equals(parsed.toCompactRawBytes(), sig)
return ui8equals(parsed.toCompactRawBytes(), sig)
} catch {
return false
}
Expand Down
10 changes: 6 additions & 4 deletions packages/crypto/src/secp256k1/operations.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
import { secp256k1 as k256 } from '@noble/curves/secp256k1'
import { sha256 } from '@noble/hashes/sha256'
import * as ui8 from 'uint8arrays'
import { SECP256K1_JWT_ALG } from '../const'
import { parseDidKey } from '../did'

import { SECP256K1_DID_PREFIX } from '../const'
import { VerifyOptions } from '../types'
import { extractMultikey, extractPrefixedBytes, hasPrefix } from '../utils'

export const verifyDidSig = async (
did: string,
data: Uint8Array,
sig: Uint8Array,
opts?: VerifyOptions,
): Promise<boolean> => {
const { jwtAlg, keyBytes } = parseDidKey(did)
if (jwtAlg !== SECP256K1_JWT_ALG) {
const prefixedBytes = extractPrefixedBytes(extractMultikey(did))
if (!hasPrefix(prefixedBytes, SECP256K1_DID_PREFIX)) {
throw new Error(`Not a secp256k1 did:key: ${did}`)
}
const keyBytes = prefixedBytes.slice(SECP256K1_DID_PREFIX.length)
return verifySig(keyBytes, data, sig, opts)
}

Expand Down
26 changes: 26 additions & 0 deletions packages/crypto/src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import * as uint8arrays from 'uint8arrays'
import {
BASE58_MULTIBASE_PREFIX,
DID_KEY_PREFIX
} from './const'

export const extractMultikey = (did: string): string => {
if (!did.startsWith(DID_KEY_PREFIX)) {
throw new Error(`Incorrect prefix for did:key: ${did}`)
}
return did.slice(DID_KEY_PREFIX.length)
}

export const extractPrefixedBytes = (multikey: string): Uint8Array => {
if (!multikey.startsWith(BASE58_MULTIBASE_PREFIX)) {
throw new Error(`Incorrect prefix for multikey: ${multikey}`)
}
return uint8arrays.fromString(
multikey.slice(BASE58_MULTIBASE_PREFIX.length),
'base58btc',
)
}

export const hasPrefix = (bytes: Uint8Array, prefix: Uint8Array): boolean => {
return uint8arrays.equals(prefix, bytes.subarray(0, prefix.byteLength))
}

0 comments on commit 9917a4f

Please sign in to comment.