╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ─────────────────╮ │src/serve_ssh_protocol.zig│ ╰──────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────╮ │1715 const algo = try takeString(&req_reader, 64); │ │1716 const pubkey_blob = try takeString(&req_reader, 4096); │ │1717 │ │1698 - if (!std.mem.eql(u8, algo, "ssh-ed25519")) { │ │1718 + if (firstCommonName(algo, &our_userauth_algos) == null) {│ │1719 try sendUserauthFailure(conn); │ │1720 continue; │ │1721 } │ ╰───────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1803 var signed: std.ArrayList(u8) = .empty; │ │1804 defer signed.deinit(allocator); │ │1805 try appendPublickeySignedData(&signed, allocator, session_id, user_name, service_name, algo, pubkey_blob); │ │1806 + │ │1807 + if (std.mem.eql(u8, algo, "ssh-ed25519")) return verifyEd25519(pubkey_blob, signature_blob, signed.items); │ │1808 + if (std.mem.eql(u8, algo, "rsa-sha2-512")) return verifyRsa(Sha512, algo, pubkey_blob, signature_blob, signed.items);│ │1809 + if (std.mem.eql(u8, algo, "rsa-sha2-256")) return verifyRsa(Sha256, algo, pubkey_blob, signature_blob, signed.items);│ │1810 + return false; │ │1811 +} │ │1812 │ │1813 +fn verifyEd25519(pubkey_blob: []const u8, signature_blob: []const u8, signed: []const u8) !bool { │ │1814 // parse pubkey_blob: string "ssh-ed25519" || string raw_pubkey │ │1815 var pubkey_reader = std.Io.Reader.fixed(pubkey_blob); │ │1816 const pk_algo = try takeString(&pubkey_reader, 64); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1832 │ │1833 const pk = Ed25519.PublicKey.fromBytes(pubkey_bytes) catch return false; │ │1834 const sig = Ed25519.Signature.fromBytes(sig_bytes); │ │1808 - sig.verify(signed.items, pk) catch return false; │ │1835 + sig.verify(signed, pk) catch return false; │ │1836 return true; │ │1837 +} │ │1838 + │ │1839 +fn verifyRsa(comptime Hash: type, algo: []const u8, pubkey_blob: []const u8, signature_blob: []const u8, signed: []const u8) !bool {│ │1840 + // parse pubkey_blob: string "ssh-rsa" || mpint e || mpint n │ │1841 + var pubkey_reader = std.Io.Reader.fixed(pubkey_blob); │ │1842 + if (!std.mem.eql(u8, try takeString(&pubkey_reader, 64), "ssh-rsa")) return false; │ │1843 + const e = std.mem.trimStart(u8, try takeString(&pubkey_reader, 1024), &.{0}); │ │1844 + const n = std.mem.trimStart(u8, try takeString(&pubkey_reader, 1024), &.{0}); │ │1845 + │ │1846 + // parse signature_blob: string algo || string sig │ │1847 + var sig_reader = std.Io.Reader.fixed(signature_blob); │ │1848 + if (!std.mem.eql(u8, try takeString(&sig_reader, 64), algo)) return false; │ │1849 + const sig = try takeString(&sig_reader, 1024); │ │1850 + if (sig.len != n.len) return false; │ │1851 + │ │1852 + const pk = rsa.PublicKey.fromBytes(e, n) catch return false; │ │1853 + switch (n.len) { │ │1854 + inline 256, 384, 512 => |len| { │ │1855 + rsa.PKCS1v1_5Signature.verify(len, sig[0..len].*, signed, pk, Hash) catch return false; │ │1856 + return true; │ │1857 + }, │ │1858 + else => return false, │ │1859 + } │ │1860 } │ │1861 │ │1862 // --------------------------------------------------------------------------- │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯