Replace secp266k1 keys with curve25519

This commit is contained in:
Jazz Turner-Baggs 2025-07-16 16:17:22 -07:00
parent d0046eabf3
commit d7b2473283
6 changed files with 42 additions and 38 deletions

View File

@ -14,7 +14,7 @@ import chronicles
type KeyEntry* = object type KeyEntry* = object
keytype: string keytype: string
keypair: SkKeyPair privateKey: PrivateKey
timestamp: int64 timestamp: int64
@ -87,16 +87,16 @@ proc createIntroBundle*(self: var Client): IntroBundle =
## the required information to send a message. ## the required information to send a message.
# Create Ephemeral keypair, save it in the key store # Create Ephemeral keypair, save it in the key store
let ephemeral_keypair = generate_keypair() let ephemeral_key = generate_key()
self.key_store[ephemeral_keypair.pubkey.toHexCompressed()] = KeyEntry( self.key_store[ephemeral_key.getPublickey().bytes().bytesToHex()] = KeyEntry(
keytype: "ephemeral", keytype: "ephemeral",
keypair: ephemeral_keypair, privateKEy: ephemeral_key,
timestamp: getTime().toUnix(), timestamp: getTime().toUnix(),
) )
result = IntroBundle( result = IntroBundle(
ident: @(self.ident.getPubkey().toRawCompressed()), ident: @(self.ident.getPubkey().bytes()),
ephemeral: @(ephemeral_keypair.pubkey.toRawCompressed()), ephemeral: @(ephemeral_key.getPublicKey().bytes()),
) )
proc createPrivateConversation*(self: var Client, participant: PublicKey, proc createPrivateConversation*(self: var Client, participant: PublicKey,
@ -114,7 +114,7 @@ proc createPrivateConversation*(self: var Client, participant: PublicKey,
proc handleIntro*(self: var Client, intro_bundle: IntroBundle): TransportMessage = proc handleIntro*(self: var Client, intro_bundle: IntroBundle): TransportMessage =
## Creates a private conversation with the given Invitebundle. ## Creates a private conversation with the given Invitebundle.
let res_pubkey = SkPublicKey.fromRaw(intro_bundle.ident) let res_pubkey = loadPublicKeyFromBytes(intro_bundle.ident)
if res_pubkey.isErr: if res_pubkey.isErr:
raise newException(ValueError, "Invalid public key in intro bundle.") raise newException(ValueError, "Invalid public key in intro bundle.")
let dest_pubkey = res_pubkey.get() let dest_pubkey = res_pubkey.get()
@ -123,9 +123,9 @@ proc handleIntro*(self: var Client, intro_bundle: IntroBundle): TransportMessage
let dst_convo_topic = topic_inbox(dest_pubkey.get_addr()) let dst_convo_topic = topic_inbox(dest_pubkey.get_addr())
let invite = InvitePrivateV1( let invite = InvitePrivateV1(
initiator: @(self.ident.getPubkey().toRawCompressed()), initiator: @(self.ident.getPubkey().bytes()),
initiator_ephemeral: @[0, 0], # TODO: Add ephemeral initiator_ephemeral: @[0, 0], # TODO: Add ephemeral
participant: @(dest_pubkey.toRawCompressed()), participant: @(dest_pubkey.bytes()),
participant_ephemeral_id: intro_bundle.ephemeral_id, participant_ephemeral_id: intro_bundle.ephemeral_id,
discriminator: "test" discriminator: "test"
) )
@ -176,7 +176,7 @@ proc recv*(self: var Client, transport_message: TransportMessage): seq[
proc processInvite*(self: var Client, invite: InvitePrivateV1) = proc processInvite*(self: var Client, invite: InvitePrivateV1) =
debug "Callback Invoked", invite = invite debug "Callback Invoked", invite = invite
createPrivateConversation(self, PublicKey.fromRaw( createPrivateConversation(self, loadPublicKeyFromBytes(
invite.initiator).get(), invite.initiator).get(),
invite.discriminator) invite.discriminator)

View File

@ -1,12 +1,11 @@
import proto_types import proto_types
import secp256k1 import crypto/ecdh
import std/[sysrand] import std/[sysrand]
export secp256k1 import results
export PublicKey, PrivateKey, bytes, createRandomKey, loadPrivateKeyFromBytes, loadPublicKeyFromBytes,
type KeyPair* = SkKeyPair getPublicKey, Dh, Result
type PublicKey* = SkPublicKey
proc encrypt_plain*[T: EncryptableTypes](frame: T): EncryptedPayload = proc encrypt_plain*[T: EncryptableTypes](frame: T): EncryptedPayload =
@ -23,11 +22,6 @@ proc decrypt_plain*[T: EncryptableTypes](ciphertext: Plaintext, t: typedesc[
result = ok(obj.get()) result = ok(obj.get())
proc generate_keypair*(): KeyPair = proc generate_key*(): PrivateKey =
var rng: Rng = urandom createRandomKey().get()
let res = SkKeyPair.random(rng)
if res.isErr:
raise newException(ValueError, "Failed to generate keypair: ")
result = res.get()

View File

@ -21,11 +21,16 @@ proc createRandomKey*(): Result[PrivateKey, string] =
return err("Failed to create HmacDrbgContext with system randomness") return err("Failed to create HmacDrbgContext with system randomness")
ok(PrivateKey(bytes: Curve25519Key.random(rng[]))) ok(PrivateKey(bytes: Curve25519Key.random(rng[])))
proc loadKeyFromBytes*(bytes: openArray[byte]): Result[PrivateKey, string] = proc loadPrivateKeyFromBytes*(bytes: openArray[byte]): Result[PrivateKey, string] =
if bytes.len != Curve25519KeySize: if bytes.len != Curve25519KeySize:
return err("Private key size must be 32 bytes") return err("Private key size must be 32 bytes")
ok(PrivateKey(bytes: intoCurve25519Key(bytes))) ok(PrivateKey(bytes: intoCurve25519Key(bytes)))
proc loadPublicKeyFromBytes*(bytes: openArray[byte]): Result[PublicKey, string] =
if bytes.len != Curve25519KeySize:
return err("Public key size must be 32 bytes")
ok(PublicKey(bytes: intoCurve25519Key(bytes)))
proc getPublicKey*(privateKey: PrivateKey): PublicKey = proc getPublicKey*(privateKey: PrivateKey): PublicKey =
PublicKey(bytes: public(privateKey.bytes)) PublicKey(bytes: public(privateKey.bytes))

View File

@ -1,12 +1,13 @@
import crypto import crypto
import utils import utils
import results
type type
Identity* = object Identity* = object
name: string name: string
keypair: KeyPair privateKey: PrivateKey
################################################# #################################################
@ -14,17 +15,17 @@ type
################################################# #################################################
proc createIdentity*(name: string): Identity = proc createIdentity*(name: string): Identity =
let keypair = generate_keypair() let privKey = createRandomKey().get()
result = Identity(name: name, keypair: keypair) result = Identity(name: name, privateKey: privKey)
################################################# #################################################
# Parameter Access # Parameter Access
################################################# #################################################
proc getPubkey*(self: Identity): PublicKey =
result = self.privateKey.getPublicKey()
proc getAddr*(self: Identity): string = proc getAddr*(self: Identity): string =
result = get_addr(self.keypair.pubkey) result = get_addr(self.getPubKey())
proc getPubkey*(self: Identity): SkPublicKey =
result = self.keypair.pubkey

View File

@ -2,8 +2,8 @@ import crypto
import proto_types import proto_types
import utils import utils
import dev import dev
import chronicles import chronicles
import results
type InviteCallback* = proc(invite: InvitePrivateV1): void type InviteCallback* = proc(invite: InvitePrivateV1): void
@ -32,7 +32,7 @@ proc wrap_env*(payload: EncryptedPayload, convo_id: string): WapEnvelopeV1 =
conversation_hint: convo_id, conversation_hint: convo_id,
) )
proc conversation_id_for*(pubkey: SkPublicKey): string = proc conversation_id_for*(pubkey: PublicKey): string =
## Generates a conversation ID based on the public key. ## Generates a conversation ID based on the public key.
return "/convo/inbox/v1" & pubkey.get_addr() return "/convo/inbox/v1" & pubkey.get_addr()

View File

@ -21,10 +21,14 @@ proc get_addr*(pubkey: SkPublicKey): string =
# TODO: Needs Spec # TODO: Needs Spec
result = hash_func(pubkey.toHexCompressed()) result = hash_func(pubkey.toHexCompressed())
proc bytesToHex*[T](bytes: openarray[T], lowercase: bool = false): string =
## Convert bytes to hex string with case option
result = ""
for b in bytes:
let hex = b.toHex(2)
result.add(if lowercase: hex.toLower() else: hex)
proc get_addr*(pubkey: PublicKey): string =
# TODO: Needs Spec
result = hash_func(pubkey.bytes().bytesToHex())
proc bytesToHex*(bytes: openarray[byte], lowercase: bool = false): string =
## Convert bytes to hex string with case option
result = ""
for b in bytes:
let hex = b.toHex(2)
result.add(if lowercase: hex.toLower() else: hex)