]> git.codecow.com Git - libnemo.git/commitdiff
Fix rolodex signature verification.
authorChris Duncan <chris@codecow.com>
Mon, 6 Jul 2026 07:58:52 +0000 (00:58 -0700)
committerChris Duncan <chris@codecow.com>
Mon, 6 Jul 2026 07:58:52 +0000 (00:58 -0700)
src/lib/rolodex.ts

index 40952dec08ec4169790d91ac21ff0b8ecfb0590d..4437e38cb9093ac56a508da57ada499486fb9b91 100644 (file)
@@ -3,29 +3,30 @@
 
 import { verify as nano25519_verify } from 'nano25519'
 import { Account } from './account'
+import { utf8 } from './convert'
 import { Database } from './database'
 
 /**
-* Represents a basic address book of Nano accounts. Multiple addresses can be
-* saved under one nickname.
-*/
+ * Represents a basic address book of Nano accounts. Multiple addresses can be
+ * saved under one nickname.
+ */
 export class Rolodex {
        /**
-       * @returns {'Rolodex'}
-       */
+        * @returns {'Rolodex'}
+        */
        static get DB_NAME (): 'Rolodex' { return 'Rolodex' }
 
        /**
-       * Adds an address to the rolodex under a specific nickname.
-       *
-       * If the name exists, add the address as a new association to that name. If
-       * the account exists under a different name, update the name. If no matches
-       * are found at all, add a new entry.
-       *
-       * @param {string} name - Contact alias for the address
-       * @param {string} address - Nano account address
-       * @returns {Promise<boolean>} Promise for true if name and address are added to the rolodex, else false
-       */
+        * Adds an address to the rolodex under a specific nickname.
+        *
+        * If the name exists, add the address as a new association to that name. If
+        * the account exists under a different name, update the name. If no matches
+        * are found at all, add a new entry.
+        *
+        * @param {string} name - Contact alias for the address
+        * @param {string} address - Nano account address
+        * @returns {Promise<boolean>} Promise for true if name and address are added to the rolodex, else false
+        */
        static async add (name: string, address: string): Promise<boolean> {
                if (name == null || name === '') {
                        throw new Error('Name is required for rolodex entries')
@@ -85,11 +86,11 @@ export class Rolodex {
        }
 
        /**
-       * Removes a Nano address from its related contact in the rolodex.
-       *
-       * @param {string} address - Nano account address
-       * @returns {Promise<boolean>} Promise for true if address successfully removed, else false
-       */
+        * Removes a Nano address from its related contact in the rolodex.
+        *
+        * @param {string} address - Nano account address
+        * @returns {Promise<boolean>} Promise for true if address successfully removed, else false
+        */
        static async deleteAddress (address: string): Promise<boolean> {
                const name = await this.getName(address)
                if (name == null) {
@@ -111,11 +112,11 @@ export class Rolodex {
        }
 
        /**
-       * Removes a contact and its related Nano addresses from the rolodex.
-       *
-       * @param {string} name - Contact name to delete
-       * @returns {Promise<boolean>} Promise for true if name and related addresses successfully removed, else false
-       */
+        * Removes a contact and its related Nano addresses from the rolodex.
+        *
+        * @param {string} name - Contact name to delete
+        * @returns {Promise<boolean>} Promise for true if name and related addresses successfully removed, else false
+        */
        static async deleteName (name: string): Promise<boolean> {
                const records = await this.getAddresses(name)
                records.push(name)
@@ -123,11 +124,11 @@ export class Rolodex {
        }
 
        /**
-       * Gets all Nano account addresses associated with a name from the rolodex.
-       *
-       * @param {string} name - Alias to look up
-       * @returns {Promise<string[]>} Promise for a list of Nano addresses associated with the name
-       */
+        * Gets all Nano account addresses associated with a name from the rolodex.
+        *
+        * @param {string} name - Alias to look up
+        * @returns {Promise<string[]>} Promise for a list of Nano addresses associated with the name
+        */
        static async getAddresses (name: string): Promise<string[]> {
                try {
                        const records = await Database.get<Record<string, string[]>>(name, this.DB_NAME)
@@ -142,10 +143,10 @@ export class Rolodex {
        }
 
        /**
-       * Gets all names stored in the rolodex.
-       *
-       * @returns {Promise<string[]>} Promise for a list of all names stored in the rolodex
-       */
+        * Gets all names stored in the rolodex.
+        *
+        * @returns {Promise<string[]>} Promise for a list of all names stored in the rolodex
+        */
        static async getAllNames (): Promise<string[]> {
                try {
                        const records = await Database.getAll<string>(this.DB_NAME)
@@ -157,11 +158,11 @@ export class Rolodex {
        }
 
        /**
-       * Gets the name associated with a specific Nano address from the rolodex.
-       *
-       * @param {string} address - Nano account address
-       * @returns {Promise<string|null>} Promise for the name associated with the address, or null if not found
-       */
+        * Gets the name associated with a specific Nano address from the rolodex.
+        *
+        * @param {string} address - Nano account address
+        * @returns {Promise<string|null>} Promise for the name associated with the address, or null if not found
+        */
        static async getName (address: string): Promise<string | null> {
                try {
                        const records = await Database.get<Record<string, string>>(address, this.DB_NAME)
@@ -174,19 +175,19 @@ export class Rolodex {
        }
 
        /**
-       * Verifies whether the public key of any Nano address saved under a specific
-       * name in the rolodex was used to sign a specific string.
-       *
-       * @param {string} name - Alias to look up
-       * @param {string} signature - Signature to use for verification
-       * @param {string} data - Signed data to verify
-       * @returns {Promise<boolean>} True if the signature was used to sign the data, else false
-       */
+        * Verifies whether the public key of any Nano address saved under a specific
+        * name in the rolodex was used to sign a specific string.
+        *
+        * @param {string} name - Alias to look up
+        * @param {string} signature - Signature to use for verification
+        * @param {string} data - Signed data to verify
+        * @returns {Promise<boolean>} True if the signature was used to sign the data, else false
+        */
        static async verify (name: string, signature: string, data: string): Promise<boolean> {
                const addresses = await this.getAddresses(name)
                for (const address of addresses) {
                        const { publicKey } = new Account(address)
-                       if (nano25519_verify(publicKey, signature, data)) {
+                       if (nano25519_verify(signature, utf8.toHex(data), publicKey)) {
                                return true
                        }
                }