Include usage in pubkey encoding

This commit is contained in:
2024-09-14 15:19:41 +02:00
parent dc66f8ee73
commit 272954fe23
5 changed files with 50 additions and 15 deletions
+41 -6
View File
@@ -11,13 +11,31 @@ export enum Usage {
export async function pubkey_toString(pubkey: CryptoKey): Promise<string> {
log.trace('pubkey_toString')
const pubkey_buff = await crypto.subtle.exportKey('spki', pubkey)
return a2b64(new Uint8Array(pubkey_buff))
const pubkey_str = a2b64(new Uint8Array(pubkey_buff))
const usage = (pubkey.usages.includes('verify') ? Usage.sign : Usage.ecdh).toString()
return `${usage}${pubkey_str}`
}
export async function pubkey_fromString(pubkey_str: string, usage: Usage): Promise<CryptoKey | null> {
export async function pubkey_fromString(pubkey_str: string): Promise<CryptoKey | null> {
log.trace('pubkey_fromString')
const pubkey = b642a(pubkey_str)
let usage: Usage;
const c = pubkey_str.at(0)
if (c === undefined) {
log.warn('Empty string ?')
return null
} else if (c === Usage.sign.toString()) usage = Usage.sign
else if (c === Usage.ecdh.toString()) usage = Usage.ecdh
else {
log.warn('Unknown usage encoded')
log.debug('Usage :', c)
return null
}
const pubkey = b642a(pubkey_str.slice(1))
if (pubkey === null) return null
try {
@@ -37,15 +55,32 @@ export async function pubkey_fromString(pubkey_str: string, usage: Usage): Promi
export async function pubkey_toBytes(pubkey: CryptoKey): Promise<Uint8Array> {
log.trace('pubkey_toBytes')
return new Uint8Array(await crypto.subtle.exportKey('raw', pubkey))
const buf = new Uint8Array(await crypto.subtle.exportKey('raw', pubkey))
const usage = pubkey.usages.includes('verify') ? Usage.sign : Usage.ecdh
return new Uint8Array([usage, ...buf])
}
export async function pubkey_fromBytes(pubkey: Uint8Array, usage: Usage): Promise<CryptoKey | null> {
export async function pubkey_fromBytes(pubkey: Uint8Array): Promise<CryptoKey | null> {
log.trace('pubkey_fromBytes')
let usage: Usage;
const o = pubkey.at(0)
if (o === undefined) {
log.warn('Empty array ?')
return null
} else if (o === Usage.sign) usage = Usage.sign
else if (o === Usage.ecdh) usage = Usage.ecdh
else {
log.warn('Unknown usage encoded')
log.debug('Usage :', o)
return null
}
try {
return await crypto.subtle.importKey(
'raw',
pubkey,
pubkey.slice(1),
usage === Usage.ecdh ? ECDH_PARAMETERS() : SIGNATURE_KEY(),
true,
usage === Usage.ecdh ? [] : ['verify']
+2 -2
View File
@@ -75,7 +75,7 @@ export default class PrivateBox {
log.warn('Data too short to contain pubkey')
return null
}
const pubkey = await pubkey_fromBytes(pubkey_buff, Usage.ecdh)
const pubkey = await pubkey_fromBytes(pubkey_buff)
if (pubkey === null) return null
const box = SecretBox.fromBytes(data.slice(1 + length))
@@ -88,6 +88,6 @@ export default class PrivateBox {
return await misc.pubkey_toString(pubkey)
}
public static async pubkey_fromString(pubkey: string): Promise<CryptoKey | null> {
return await misc.pubkey_fromString(pubkey, misc.Usage.ecdh)
return await misc.pubkey_fromString(pubkey)
}
}
+1 -1
View File
@@ -63,6 +63,6 @@ export default class PrivateWrap {
return await misc.pubkey_toString(pubkey)
}
public static async pubkey_fromString(pubkey: string): Promise<CryptoKey | null> {
return await misc.pubkey_fromString(pubkey, misc.Usage.ecdh)
return await misc.pubkey_fromString(pubkey)
}
}
+1 -1
View File
@@ -37,7 +37,7 @@ export async function pubkey_toString(pubkey: CryptoKey): Promise<string> {
return await misc.pubkey_toString(pubkey)
}
export async function pubkey_fromString(pubkey: string): Promise<CryptoKey | null> {
return await misc.pubkey_fromString(pubkey, misc.Usage.sign)
return await misc.pubkey_fromString(pubkey)
}
export function signature_toString(signature: Uint8Array): string {
+5 -5
View File
@@ -1,13 +1,13 @@
import {expect, test} from 'bun:test'
import {PrivateBox, PrivateWrap, SecretBox, signature} from '..'
import {pubkey_fromBytes, pubkey_fromString, pubkey_toBytes, pubkey_toString, Usage} from '../src/misc'
import {pubkey_fromBytes, pubkey_fromString, pubkey_toBytes, pubkey_toString} from '../src/misc'
test('Private box', async () => {
const message = crypto.getRandomValues(new Uint8Array(8))
const k = await PrivateBox.gen(false)
const ser = await pubkey_toString(k.publicKey)
const de = await pubkey_fromString(ser, Usage.ecdh)
const de = await pubkey_fromString(ser)
expect(de).not.toBeNull()
const box = await PrivateBox.encrypt(message, de!)
@@ -19,7 +19,7 @@ test('Private wrap', async () => {
const k = await PrivateWrap.gen(false)
const ser = await pubkey_toString(k.publicKey)
const de = await pubkey_fromString(ser, Usage.ecdh)
const de = await pubkey_fromString(ser)
expect(de).not.toBeNull()
const message = crypto.getRandomValues(new Uint8Array(8))
@@ -42,7 +42,7 @@ test('Signature', async () => {
expect(signed).not.toBeNull()
const ser = await pubkey_toString(k.publicKey)
const de = await pubkey_fromString(ser, Usage.sign)
const de = await pubkey_fromString(ser)
expect(de).not.toBeNull()
const verification = await signature.verify(message, de!, signed!)
@@ -55,7 +55,7 @@ test('Byte serialization', async () => {
expect(signed).not.toBeNull()
const ser = await pubkey_toBytes(k.publicKey)
const de = await pubkey_fromBytes(ser, Usage.sign)
const de = await pubkey_fromBytes(ser)
expect(de).not.toBeNull()
const verification = await signature.verify(message, de!, signed!)