diff --git a/.github/workflows/signature.yml b/.github/workflows/signature.yml new file mode 100644 index 000000000..d57747d6c --- /dev/null +++ b/.github/workflows/signature.yml @@ -0,0 +1,64 @@ +name: '@narval/signature CI' + +on: + push: + paths: + - packages/signature/** + - .github/workflows/signature.yml + - jest.config.ts + - jest.preset.js + - .eslintrc.json + - .prettierrc + - package.json + - package-lock.json + +jobs: + build-and-test: + name: Build and test + + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@master + + - name: Install Node.js + uses: actions/setup-node@v3 + with: + node-version: '20.4.0' + + - name: Install dependencies + run: | + make install/ci + + - name: Code format + shell: bash + run: | + make signature/format/check + make signature/lint/check + + - name: Test types + shell: bash + run: | + make signature/test/type + + - name: Test upstream application types + shell: bash + run: | + make policy-engine/test/type + + - name: Test unit + shell: bash + run: | + make signature/test/unit + + - name: Send Slack notification on failure + if: failure() && github.ref == 'refs/heads/main' + uses: 8398a7/action-slack@v3 + with: + username: GitHub + author_name: '@narval/signature CI failed' + status: ${{ job.status }} + fields: message,commit,author + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} diff --git a/packages/signature/src/lib/__test__/unit/sign.spec.ts b/packages/signature/src/lib/__test__/unit/sign.spec.ts index dd5105ffa..9c9dd8037 100644 --- a/packages/signature/src/lib/__test__/unit/sign.spec.ts +++ b/packages/signature/src/lib/__test__/unit/sign.spec.ts @@ -38,7 +38,14 @@ describe('sign', () => { it('should sign build & sign es256 JWT correctly with a PEM', async () => { const key = await importPKCS8(PRIVATE_KEY_PEM, Alg.ES256) const jwk = await exportJWK(key) - const jwt = await signJwt(payload, { ...jwk, alg: Alg.ES256, crv: 'P-256', kty: 'EC', kid: 'somekid' }) + const jwt = await signJwt(payload, { + ...jwk, + alg: Alg.ES256, + crv: 'P-256', + kty: 'EC', + kid: 'somekid', + use: undefined + }) const verified = await jwtVerify(jwt, key) expect(verified.payload).toEqual(payload) diff --git a/packages/signature/src/lib/sign.ts b/packages/signature/src/lib/sign.ts index 6bfbc9158..6692a70de 100644 --- a/packages/signature/src/lib/sign.ts +++ b/packages/signature/src/lib/sign.ts @@ -3,9 +3,9 @@ import { sha256 as sha256Hash } from '@noble/hashes/sha256' import { keccak_256 as keccak256 } from '@noble/hashes/sha3' import { SignJWT, base64url, importJWK } from 'jose' import { isHex, signatureToHex, toBytes, toHex } from 'viem' +import { hash } from './hash-request' import { privateKeySchema } from './schemas' import { EcdsaSignature, Header, Hex, Jwk, JwsdHeader, Payload, PrivateKey, SigningAlg } from './types' -import { hash } from './hash-request' import { hexToBase64Url } from './utils' import { validate } from './validate' diff --git a/packages/signature/src/lib/utils.ts b/packages/signature/src/lib/utils.ts index 9ab6be8fc..a0a91be62 100644 --- a/packages/signature/src/lib/utils.ts +++ b/packages/signature/src/lib/utils.ts @@ -155,8 +155,8 @@ const rsaKeyToKid = (jwk: Jwk) => { const generateRsaKeyPair = async ( opts: { keyId?: string - modulusLength?: number, - use?: Use, + modulusLength?: number + use?: Use } = { modulusLength: 2048 } @@ -175,9 +175,9 @@ const generateRsaKeyPair = async ( alg: Alg.RS256, kty: KeyTypes.RSA, crv: undefined, - use: opts.use || undefined, + use: opts.use || undefined } - jwk.kid = opts.keyId || rsaKeyToKid(jwk); + jwk.kid = opts.keyId || rsaKeyToKid(jwk) const pk = validate(rsaPrivateKeySchema, jwk, 'Invalid RSA Private Key JWK') return pk @@ -187,8 +187,8 @@ export const generateJwk = async ( alg: Alg, opts?: { keyId?: string - modulusLength?: number, - use?: Use, + modulusLength?: number + use?: Use } ): Promise => { switch (alg) { diff --git a/packages/signature/src/lib/verify.ts b/packages/signature/src/lib/verify.ts index e191ee37b..178d8ad10 100644 --- a/packages/signature/src/lib/verify.ts +++ b/packages/signature/src/lib/verify.ts @@ -101,19 +101,19 @@ export async function verifyJwt(jwt: string, jwk: Jwk): Promise { } export async function verifyJwsd(jws: string, jwk: PublicKey): Promise { - const { header, payload, signature } = decodeJwsd(jws) + const { header, payload, signature } = decodeJwsd(jws) - if (header.alg === SigningAlg.EIP191) { - await verifyEip191(jws, jwk) - } else { - // TODO: Implement other algs individually without jose - const joseJwk = await importJWK(jwk) - await jwtVerify(jws, joseJwk) - } + if (header.alg === SigningAlg.EIP191) { + await verifyEip191(jws, jwk) + } else { + // TODO: Implement other algs individually without jose + const joseJwk = await importJWK(jwk) + await jwtVerify(jws, joseJwk) + } - return { - header, - payload, - signature - } + return { + header, + payload, + signature + } }