import { describe, expect, it } from 'vitest' import { fingerprintOf, keyTypeOf } from '../src/main/session/hostKey' /** * A real ed25519 host key, with the fingerprint `ssh-keygen -lf` prints for it: * * $ ssh-keygen -lf host_key.pub * 256 SHA256:ASmbFHszdZLp5YkSiJnqmGfAhpZKOZwQJnk3rLUo4Xo (ED25519) * * The expected value is pinned rather than computed so the test proves the * *format*, not merely that the function is self-consistent. A fingerprint that * does not match what ssh-keygen shows is one the user cannot check against * anything, which defeats the point of showing it at all. */ const ED25519_PUBLIC_KEY = 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKzewpDb5LqzDdJeN9GQVNBzIVE3ZPZ9cGWFpurXr1o8 test@host' const ED25519_FINGERPRINT = 'SHA256:ASmbFHszdZLp5YkSiJnqmGfAhpZKOZwQJnk3rLUo4Xo' function blobOf(publicKeyLine: string): Buffer { const base64 = publicKeyLine.trim().split(/\s+/)[1] if (!base64) throw new Error('not a public key line') return Buffer.from(base64, 'base64') } describe('keyTypeOf', () => { it('reads the algorithm name out of the wire format', () => { expect(keyTypeOf(blobOf(ED25519_PUBLIC_KEY))).toBe('ssh-ed25519') }) it('returns unknown rather than throwing on a malformed blob', () => { // A short or bogus blob must not take down a connection attempt — it just // cannot be identified, and the fingerprint check will still be shown. expect(keyTypeOf(Buffer.alloc(0))).toBe('unknown') expect(keyTypeOf(Buffer.from([0, 0]))).toBe('unknown') // Declares a 4GB name. expect(keyTypeOf(Buffer.from([0xff, 0xff, 0xff, 0xff, 1, 2, 3]))).toBe('unknown') }) }) describe('fingerprintOf', () => { it('matches the OpenSSH SHA256 fingerprint exactly', () => { expect(fingerprintOf(blobOf(ED25519_PUBLIC_KEY))).toBe(ED25519_FINGERPRINT) }) it('strips base64 padding, as OpenSSH does', () => { expect(fingerprintOf(blobOf(ED25519_PUBLIC_KEY))).not.toContain('=') }) it('is stable for the same key', () => { const blob = blobOf(ED25519_PUBLIC_KEY) expect(fingerprintOf(blob)).toBe(fingerprintOf(blob)) }) it('differs for a different key', () => { const a = blobOf(ED25519_PUBLIC_KEY) const b = Buffer.from(a) b[b.length - 1] ^= 0x01 expect(fingerprintOf(b)).not.toBe(fingerprintOf(a)) }) it('is a SHA256 digest, not a truncated or padded one', () => { // 32 bytes base64-encodes to 44 characters, 43 once padding is stripped. const digest = fingerprintOf(blobOf(ED25519_PUBLIC_KEY)).replace('SHA256:', '') expect(digest).toHaveLength(43) }) })