Skip to content

Commit

Permalink
Add
Browse files Browse the repository at this point in the history
  • Loading branch information
OR13 committed Feb 25, 2024
1 parent 879fe5c commit 8296a31
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 241 deletions.
2 changes: 1 addition & 1 deletion examples/hpke.direct.diag
Original file line number Diff line number Diff line change
@@ -1 +1 @@
16([h'a1011823', {4: "[email protected]", -4: h'04857b9f69d979aaad64a4dda88b13451a4f50ad4cae017d1ba915922f0b6ffbc80e48a430b6052e4a9c62a5174596894064380292cbe451abd9f11b950803759f'}, h'c1b033e9c44096d7e9aab87df46478c21ff51829b3b7e16c11c176ba9ec50dabc8035a0e7b3bedbe56dd4bd5360de04e7a189e9096321660dd706e014db3c0b8d1f86b9b2d544a708505ade4ea15a9ac'])
16([h'a1011823', {4: "[email protected]", -4: h'04c1132cc6e79a1fb92d0b26eed30c81682c755ee11f40c25ecadd04b60067c91e326be9d3e598a4ff466a503adbf6aaf5ae65c02b5373b41545fdf4d5688e0a6a'}, h'3b763f48dbe3ec5a77655a4184a50694dd5ed918d7afa4898711f0a3b64daa59dfe3285af27c410b142054ee2b487cded3fda822f1d988bdc79cc5360c538a305fdd6867567872626385c8ae4cb2f275'])
2 changes: 1 addition & 1 deletion examples/hpke.direct.party-id.diag
Original file line number Diff line number Diff line change
@@ -1 +1 @@
16([h'a301182334536469643a6578616d706c653a70617274792d7537536469643a6578616d706c653a70617274792d76', {4: "[email protected]", -4: h'04ff966068fc4a6721c5ca346378960d357e57f2ffb2b2a6ed3b1068c16e47c43add53cafcfd1115233612af72211bea46d74f4d14674874f3b0cd74b58dc68b48'}, h'05272d40e4a6a5c4a21d67942b591d63e43dea1e2a107bce6448a7a1db5039d88669d4d931f7bc0b2ad182ab2236fd2974a9b749e1f1fdb6ca741ddf7fadf72fe633176aad1ac736d68645958519c987'])
16([h'a301182334536469643a6578616d706c653a70617274792d7537536469643a6578616d706c653a70617274792d76', {4: "[email protected]", -4: h'04abbef2a5d77642a6537962f5fa35e5ddf55939dc941277f972d75121ad38d9ad9bcd186bf774f13cad6716bcf7aa5618ca1c8bed2bead9f6847797b226fb0b28'}, h'cfa98068f705cddf86970d94636e9470349eb81bd31732594a85cdbe72d9ed3128c09052397000d5ff5fb76674de5e02285b616da12522990f9805a00ae1e030abe3bcf79d54979b63a39e0ab7e06b92'])
2 changes: 1 addition & 1 deletion examples/hpke.wrap.diag
Original file line number Diff line number Diff line change
@@ -1 +1 @@
96([h'a10101', {5: 64(h'f2c5fa1399b626cd4ed64a252a064731')}, h'32d7bcbace2e8a55a3b3c4a67919bbbb79ffa6dd6b1654591555fd9de7ed2e0d50b65d6305d56fd298d8ed83ee0a8adf55fa38755e846a205f7669495c9d03e26377061dbb292948e863ea86bfabf48d', [[h'a1011823', {4: "[email protected]", -4: h'046eb31da629cba4c1e2406566911edd2ef0f0499d3bde3beec6e8c65f986e29eae1748ac5146c5cd9095bd13540e97b70458c86ae9a1c9e548cb81dac512e95be'}, h'1d6aa896a1256e594b43d847b6987fc45b0c37687c8e0c0c951a42df8764a035']]])
96([h'a10101', {5: 64(h'b58687fd100844ed0e09f52403c583da')}, h'f410bbdd5f9be2d71ed22e631dac557421191b461b5beba2bb4b3c63f257dbbe5b603fe16126cf1c97adf004beee15c9ea992a9c97cb01e9fdf806839d7deb43161aebd5ddbb88899e3fb2c263bbb483', [[h'a1011823', {4: "[email protected]", -4: h'04f9258bf3f02658ab71cc71da6c1b76953b71dbaba8fddb27aa6a061f1d9fe771d8e3942ff9a2908508e5b1ef84e670f050daeb06c9531b3e45749e230c092b8c'}, h'907610d71192aab229469a5390a66e98f654add5fb27ebe250b0041354d6f22c']]])
89 changes: 89 additions & 0 deletions src/cose/encrypt/hpke/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { suites, JOSE_HPKE_ALG } from "./suites"
import subtle from '../../../crypto/subtleCryptoProvider'
import { generateKeyPair, exportJWK, calculateJwkThumbprintUri } from "jose"



import { encode } from 'cbor-web';

export const computeHPKEAad = (protectedHeader: any, protectedRecipientHeader?: any) => {
if (protectedRecipientHeader) {
// not sure what to do when recipient protected header exists...
return encode([protectedHeader, protectedRecipientHeader])
}
return protectedHeader
}

export type JWK = {
kid?: string
alg?: string
kty: string
crv: string
}

export const isKeyAlgorithmSupported = (recipient: JWK) => {
const supported_alg = Object.keys(suites) as string[]
return supported_alg.includes(`${recipient.alg}`)
}

export const formatJWK = (jwk: any) => {
const { kid, alg, kty, crv, x, y, d } = jwk
return JSON.parse(JSON.stringify({
kid, alg, kty, crv, x, y, d
}))
}

export const publicFromPrivate = (privateKeyJwk: any) => {
const { kid, alg, kty, crv, x, y, ...rest } = privateKeyJwk
return {
kid, alg, kty, crv, x, y
}
}

export const publicKeyFromJwk = async (publicKeyJwk: any) => {
const api = (await subtle())
const publicKey = await api.importKey(
'jwk',
publicKeyJwk,
{
name: 'ECDH',
namedCurve: publicKeyJwk.crv,
},
true,
[],
)
return publicKey;
}

export const privateKeyFromJwk = async (privateKeyJwk: any) => {
const api = (await subtle())
const privateKey = await api.importKey(
'jwk',
privateKeyJwk,
{
name: 'ECDH',
namedCurve: privateKeyJwk.crv,
},
true,
['deriveBits', 'deriveKey'],
)
return privateKey
}

export const generate = async (alg: JOSE_HPKE_ALG) => {
if (!suites[alg]) {
throw new Error('Algorithm not supported')
}
let kp;
if (alg.includes('P256')) {
kp = await generateKeyPair('ECDH-ES+A256KW', { crv: 'P-256', extractable: true })
} else if (alg.includes('P384')) {
kp = await generateKeyPair('ECDH-ES+A256KW', { crv: 'P-384', extractable: true })
} else {
throw new Error('Could not generate private key for ' + alg)
}
const privateKeyJwk = await exportJWK(kp.privateKey);
privateKeyJwk.kid = await calculateJwkThumbprintUri(privateKeyJwk)
privateKeyJwk.alg = alg;
return formatJWK(privateKeyJwk)
}
104 changes: 2 additions & 102 deletions src/cose/encrypt/hpke/direct.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,111 +3,11 @@
import { COSE_Encrypt0, Direct, Protected, Unprotected, UnprotectedHeader } from '../../Params'
import { RequestDirectEncryption, RequestDirectDecryption } from '../types'
import { Tagged, decodeFirst, encodeAsync } from "cbor-web"
import { generateKeyPair, exportJWK, calculateJwkThumbprintUri } from "jose"

export type JOSE_HPKE_ALG = `HPKE-Base-P256-SHA256-AES128GCM` | `HPKE-Base-P384-SHA256-AES128GCM`
import subtle from '../../../crypto/subtleCryptoProvider'
import { computeInfo } from './computeInfo'
import { suites } from './suites'
import { encode } from 'cbor-web';
export type JWK = {
kid?: string
alg?: string
kty: string
crv: string
}

export type JWKS = {
keys: JWK[]
}

export type HPKERecipient = {
encrypted_key: string
header: {
kid?: string
alg?: string
epk?: JWK
encapsulated_key: string,
}
}


export const isKeyAlgorithmSupported = (recipient: JWK) => {
const supported_alg = Object.keys(suites) as string[]
return supported_alg.includes(`${recipient.alg}`)
}

export const formatJWK = (jwk: any) => {
const { kid, alg, kty, crv, x, y, d } = jwk
return JSON.parse(JSON.stringify({
kid, alg, kty, crv, x, y, d
}))
}

export const publicFromPrivate = (privateKeyJwk: any) => {
const { kid, alg, kty, crv, x, y, ...rest } = privateKeyJwk
return {
kid, alg, kty, crv, x, y
}
}

export const publicKeyFromJwk = async (publicKeyJwk: any) => {
const api = (await subtle())
const publicKey = await api.importKey(
'jwk',
publicKeyJwk,
{
name: 'ECDH',
namedCurve: publicKeyJwk.crv,
},
true,
[],
)
return publicKey;
}
import { suites, JOSE_HPKE_ALG } from './suites'

export const privateKeyFromJwk = async (privateKeyJwk: any) => {
const api = (await subtle())
const privateKey = await api.importKey(
'jwk',
privateKeyJwk,
{
name: 'ECDH',
namedCurve: privateKeyJwk.crv,
},
true,
['deriveBits', 'deriveKey'],
)
return privateKey
}

export const generate = async (alg: JOSE_HPKE_ALG) => {
if (!suites[alg]) {
throw new Error('Algorithm not supported')
}
let kp;
if (alg.includes('P256')) {
kp = await generateKeyPair('ECDH-ES+A256KW', { crv: 'P-256', extractable: true })
} else if (alg.includes('P384')) {
kp = await generateKeyPair('ECDH-ES+A256KW', { crv: 'P-384', extractable: true })
} else {
throw new Error('Could not generate private key for ' + alg)
}
const privateKeyJwk = await exportJWK(kp.privateKey);
privateKeyJwk.kid = await calculateJwkThumbprintUri(privateKeyJwk)
privateKeyJwk.alg = alg;
return formatJWK(privateKeyJwk)
}



const computeHPKEAad = (protectedHeader: any, protectedRecipientHeader?: any) => {
if (protectedRecipientHeader) {
// not sure what to do when recipient protected header exists...
return encode([protectedHeader, protectedRecipientHeader])
}
return protectedHeader
}
import { publicKeyFromJwk, privateKeyFromJwk, computeHPKEAad } from './common'

export const encryptDirect = async (req: RequestDirectEncryption) => {
if (req.unprotectedHeader === undefined) {
Expand Down
2 changes: 2 additions & 0 deletions src/cose/encrypt/hpke/suites.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@

import { AeadId, CipherSuite, KdfId, KemId } from "hpke-js";

export type JOSE_HPKE_ALG = `HPKE-Base-P256-SHA256-AES128GCM` | `HPKE-Base-P384-SHA256-AES128GCM`

export const primaryAlgorithm = {
'label': `HPKE-Base-P256-SHA256-AES128GCM`,
'value': 35
Expand Down
140 changes: 4 additions & 136 deletions src/cose/encrypt/hpke/wrap.ts
Original file line number Diff line number Diff line change
@@ -1,147 +1,15 @@

import { createAAD } from '../utils'

import { COSE_Encrypt, COSE_Encrypt0, Direct, Protected, Unprotected, UnprotectedHeader } from '../../Params'

import { RequestWrapDecryption, RequestWrapEncryption, RequestDirectEncryption, RequestDirectDecryption } from '../types'
import { COSE_Encrypt, Protected, Unprotected, UnprotectedHeader } from '../../Params'
import { RequestWrapDecryption, RequestWrapEncryption, } from '../types'
import { EMPTY_BUFFER } from "../../../cbor"

import { Tagged, decodeFirst, encodeAsync } from "cbor-web"

import { generateKeyPair, exportJWK, calculateJwkThumbprintUri } from "jose"

import { AeadId, CipherSuite, KdfId, KemId } from "hpke-js";

import { computeInfo } from './computeInfo'

export type JOSE_HPKE_ALG = `HPKE-Base-P256-SHA256-AES128GCM` | `HPKE-Base-P384-SHA256-AES128GCM`
import subtle from '../../../crypto/subtleCryptoProvider'

import * as aes from '../aes'
import { encode } from 'cbor-web';

import { toArrayBuffer } from '../../../cbor'

export type JWK = {
kid?: string
alg?: string
kty: string
crv: string
}

export type JWKS = {
keys: JWK[]
}

export type HPKERecipient = {
encrypted_key: string
header: {
kid?: string
alg?: string
epk?: JWK
encapsulated_key: string,
}
}

export const suites = {
['HPKE-Base-P256-SHA256-AES128GCM']: new CipherSuite({
kem: KemId.DhkemP256HkdfSha256,
kdf: KdfId.HkdfSha256,
aead: AeadId.Aes128Gcm,
}),
['HPKE-Base-P384-SHA256-AES128GCM']: new CipherSuite({
kem: KemId.DhkemP384HkdfSha384,
kdf: KdfId.HkdfSha256,
aead: AeadId.Aes128Gcm,
})
}

export const isKeyAlgorithmSupported = (recipient: JWK) => {
const supported_alg = Object.keys(suites) as string[]
return supported_alg.includes(`${recipient.alg}`)
}

export const formatJWK = (jwk: any) => {
const { kid, alg, kty, crv, x, y, d } = jwk
return JSON.parse(JSON.stringify({
kid, alg, kty, crv, x, y, d
}))
}

export const publicFromPrivate = (privateKeyJwk: any) => {
const { kid, alg, kty, crv, x, y, ...rest } = privateKeyJwk
return {
kid, alg, kty, crv, x, y
}
}

export const publicKeyFromJwk = async (publicKeyJwk: any) => {
const api = (await subtle())
const publicKey = await api.importKey(
'jwk',
publicKeyJwk,
{
name: 'ECDH',
namedCurve: publicKeyJwk.crv,
},
true,
[],
)
return publicKey;
}

export const privateKeyFromJwk = async (privateKeyJwk: any) => {
const api = (await subtle())
const privateKey = await api.importKey(
'jwk',
privateKeyJwk,
{
name: 'ECDH',
namedCurve: privateKeyJwk.crv,
},
true,
['deriveBits', 'deriveKey'],
)
return privateKey
}

export const generate = async (alg: JOSE_HPKE_ALG) => {
if (!suites[alg]) {
throw new Error('Algorithm not supported')
}
let kp;
if (alg.includes('P256')) {
kp = await generateKeyPair('ECDH-ES+A256KW', { crv: 'P-256', extractable: true })
} else if (alg.includes('P384')) {
kp = await generateKeyPair('ECDH-ES+A256KW', { crv: 'P-384', extractable: true })
} else {
throw new Error('Could not generate private key for ' + alg)
}
const privateKeyJwk = await exportJWK(kp.privateKey);
privateKeyJwk.kid = await calculateJwkThumbprintUri(privateKeyJwk)
privateKeyJwk.alg = alg;
return formatJWK(privateKeyJwk)
}

export const primaryAlgorithm = {
'label': `HPKE-Base-P256-SHA256-AES128GCM`,
'value': 35
}

export const secondaryAlgorithm = {
'label': `HPKE-Base-P384-SHA384-AES256GCM`,
'value': 37
}



const computeHPKEAad = (protectedHeader: any, protectedRecipientHeader?: any) => {
if (protectedRecipientHeader) {
// not sure what to do when recipient protected header exists...
return encode([protectedHeader, protectedRecipientHeader])
}
return protectedHeader
}
import { suites, JOSE_HPKE_ALG } from './suites'
import { publicKeyFromJwk, computeHPKEAad, privateKeyFromJwk } from './common'

export const encryptWrap = async (req: RequestWrapEncryption) => {
if (req.unprotectedHeader === undefined) {
Expand Down

0 comments on commit 8296a31

Please sign in to comment.