Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SSH SFTP "Signature verification failed: TypeError: Unknown digest algorithm: sha1" #24118

Closed
gorillapower opened this issue Jun 6, 2024 · 0 comments · Fixed by #24392
Closed
Labels
bug Something isn't working correctly crypto Related to node:crypto or WebCrypto node compat

Comments

@gorillapower
Copy link

Version: Deno 1.44.0

Attempting to connect to SFTP server with the following setup, it seems that the algo value of sha1 is rejected by Deno during the verify call in crypto/sig.ts.

Funnily enough if I intercept the value and change it to sha-1 (by manually editing the call at verify in registry.npmjs.org/ssh2/1.15.0/lib/protocol/keyParser.js:408:18) it is accepted but then fails further in the code when creating a hash,

Fails with Unknown digest algorithm: sha1

{"ts":1717686646409,"type":"info","message":"CLIENT[sftp]: connect: Debugging turned on"}
{"ts":1717686646409,"type":"info","message":"CLIENT[sftp]: ssh2-sftp-client Version: 10.0.3  {
 "node": "20.11.1",
 "uv": "1.43.0",
 "zlib": "1.2.11",
 "brotli": "1.0.9",
 "ares": "1.18.1",
 "modules": "108",
 "nghttp2": "1.47.0",
 "napi": "8",
 "llhttp": "6.0.10",
 "openssl": "3.0.7+quic",
 "cldr": "41.0",
 "icu": "71.1",
 "tz": "2022b",
 "unicode": "14.0",
 "ngtcp2": "0.8.1",
 "nghttp3": "0.7.0",
 "deno": "1.44.0",
 "v8": "12.6.228.3",
 "typescript": "5.4.5"
}"}
{"ts":1717686646410,"type":"info","message":"CLIENT[sftp]: connect: Connect attempt 1"}
{"ts":1717686646415,"type":"info","message":"Custom crypto binding not available"}
{"ts":1717686646415,"type":"info","message":"Local ident: 'SSH-2.0-ssh2js1.15.0'"}
{"ts":1717686646416,"type":"info","message":"Client: Trying 127.0.0.1 on port 22 ..."}
{"ts":1717686646430,"type":"info","message":"Socket connected"}
{"ts":1717686646867,"type":"info","message":"Remote ident: 'SSH-2.0-OpenSSH_5.3'"}
{"ts":1717686646867,"type":"info","message":"Outbound: Sending KEXINIT"}
{"ts":1717686647062,"type":"info","message":"Inbound: Handshake in progress"}
{"ts":1717686647062,"type":"info","message":"Handshake: (local) KEX method: curve25519-sha256@libssh.org,curve25519-sha256,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group14-sha256,diffie-hellman-group15-sha512,diffie-hellman-group16-sha512,diffie-hellman-group17-sha512,diffie-hellman-group18-sha512,ext-info-c,kex-strict-c-v00@openssh.com"}
{"ts":1717686647062,"type":"info","message":"Handshake: (remote) KEX method: diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1"}
{"ts":1717686647062,"type":"info","message":"Handshake: KEX algorithm: diffie-hellman-group-exchange-sha256"}
{"ts":1717686647062,"type":"info","message":"Handshake: (local) Host key format: ssh-rsa"}
{"ts":1717686647062,"type":"info","message":"Handshake: (remote) Host key format: ssh-rsa,ssh-dss"}
{"ts":1717686647062,"type":"info","message":"Handshake: Host key format: ssh-rsa"}
{"ts":1717686647062,"type":"info","message":"Handshake: (local) C->S cipher: aes128-gcm@openssh.com,aes256-gcm@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr"}
{"ts":1717686647062,"type":"info","message":"Handshake: (remote) C->S cipher: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se"}
{"ts":1717686647062,"type":"info","message":"Handshake: C->S Cipher: aes128-ctr"}
{"ts":1717686647062,"type":"info","message":"Handshake: (local) S->C cipher: aes128-gcm@openssh.com,aes256-gcm@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr"}
{"ts":1717686647062,"type":"info","message":"Handshake: (remote) S->C cipher: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se"}
{"ts":1717686647062,"type":"info","message":"Handshake: S->C cipher: aes128-ctr"}
{"ts":1717686647062,"type":"info","message":"Handshake: (local) C->S MAC: hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1"}
{"ts":1717686647062,"type":"info","message":"Handshake: (remote) C->S MAC: hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96"}
{"ts":1717686647062,"type":"info","message":"Handshake: C->S MAC: hmac-sha2-256"}
{"ts":1717686647062,"type":"info","message":"Handshake: (local) S->C MAC: hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1"}
{"ts":1717686647062,"type":"info","message":"Handshake: (remote) S->C MAC: hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96"}
{"ts":1717686647062,"type":"info","message":"Handshake: S->C MAC: hmac-sha2-256"}
{"ts":1717686647062,"type":"info","message":"Handshake: (local) C->S compression: none,zlib@openssh.com,zlib"}
{"ts":1717686647062,"type":"info","message":"Handshake: (remote) C->S compression: none,zlib@openssh.com"}
{"ts":1717686647062,"type":"info","message":"Handshake: C->S compression: none"}
{"ts":1717686647062,"type":"info","message":"Handshake: (local) S->C compression: none,zlib@openssh.com,zlib"}
{"ts":1717686647062,"type":"info","message":"Handshake: (remote) S->C compression: none,zlib@openssh.com"}
{"ts":1717686647062,"type":"info","message":"Handshake: S->C compression: none"}
{"ts":1717686647063,"type":"info","message":"Outbound: Sending KEXDH_GEX_REQUEST"}
{"ts":1717686647371,"type":"info","message":"Received DH GEX Group"}
{"ts":1717686647389,"type":"info","message":"Outbound: Sending KEXDH_GEX_INIT"}
{"ts":1717686647675,"type":"info","message":"Received DH GEX Reply"}
{"ts":1717686647676,"type":"info","message":"Received DH Reply"}
{"ts":1717686647676,"type":"info","message":"Host accepted by default (no verification)"}
{"ts":1717686647676,"type":"info","message":"Host accepted (verified)"}
{"ts":1717686647676,"type":"info","message":"Outbound: Sending NEWKEYS"}
{"ts":1717686647676,"type":"info","message":"Inbound: NEWKEYS"}
{"ts":1717686647695,"type":"info","message":"Verifying signature ..."}
{"ts":1717686647698,"type":"info","message":"Signature verification failed: TypeError: Unknown digest algorithm: sha1
    at VerifyImpl.verify (ext:deno_node/internal/crypto/sig.ts:75:12)
    at verifyOneShot (ext:deno_node/internal/crypto/sig.ts:109:49)
    at OpenSSH_Public.verify (file:///home/martin/.cache/deno/npm/registry.npmjs.org/ssh2/1.15.0/lib/protocol/keyParser.js:408:18)
    at DHGroupExchange.finish (file:///home/martin/.cache/deno/npm/registry.npmjs.org/ssh2/1.15.0/lib/protocol/kex.js:698:40)
    at DHGroupExchange.parse (file:///home/martin/.cache/deno/npm/registry.npmjs.org/ssh2/1.15.0/lib/protocol/kex.js:1267:23)
    at Protocol.onKEXPayload (file:///home/martin/.cache/deno/npm/registry.npmjs.org/ssh2/1.15.0/lib/protocol/kex.js:1826:20)
    at NullDecipher.decrypt (file:///home/martin/.cache/deno/npm/registry.npmjs.org/ssh2/1.15.0/lib/protocol/crypto.js:612:26)
    at Protocol.parsePacket [as _parse] (file:///home/martin/.cache/deno/npm/registry.npmjs.org/ssh2/1.15.0/lib/protocol/Protocol.js:2028:25)
    at Protocol.parse (file:///home/martin/.cache/deno/npm/registry.npmjs.org/ssh2/1.15.0/lib/protocol/Protocol.js:313:16)
    at Socket.<anonymous> (file:///home/martin/.cache/deno/npm/registry.npmjs.org/ssh2/1.15.0/lib/client.js:775:21)
    at Socket.emit (ext:deno_node/_stream.mjs:1851:9)
    at addChunk (ext:deno_node/_stream.mjs:2873:16)
    at readableAddChunk (ext:deno_node/_stream.mjs:2852:13)
    at Socket.Readable.push (ext:deno_node/_stream.mjs:2791:14)
    at TCP.onStreamRead [as onread] (ext:deno_node/internal/stream_base_commons.ts:152:23)
    at TCP.#read (ext:deno_node/internal_binding/stream_wrap.ts:166:12)"}

Stacktrace if the algo value is changed to sha-1 at registry.npmjs.org/ssh2/1.15.0/lib/protocol/keyParser.js:408:18

{"ts":1717687968326,"type":"info","message":"Host accepted by default (no verification)"}
{"ts":1717687968326,"type":"info","message":"Host accepted (verified)"}
{"ts":1717687968326,"type":"info","message":"Outbound: Sending NEWKEYS"}
{"ts":1717687968326,"type":"info","message":"Inbound: NEWKEYS"}
{"ts":1717687968346,"type":"info","message":"Verifying signature ..."}
{"ts":1717687968348,"type":"info","message":"Signature verification failed: TypeError: Unknown hash algorithm: sha-1
    at new Hash (ext:deno_node/internal/crypto/hash.ts:42:15)
    at createHash (ext:deno_node/internal/crypto/hash.ts:139:10)
    at new VerifyImpl (ext:deno_node/internal/crypto/sig.ts:58:17)
    at Verify (ext:deno_node/internal/crypto/sig.ts:79:10)
    at verifyOneShot (ext:deno_node/internal/crypto/sig.ts:109:18)
    at OpenSSH_Public.verify (file:///home/martin/.cache/deno/npm/registry.npmjs.org/ssh2/1.15.0/lib/protocol/keyParser.js:410:18)
    at DHGroupExchange.finish (file:///home/martin/.cache/deno/npm/registry.npmjs.org/ssh2/1.15.0/lib/protocol/kex.js:698:40)
    at DHGroupExchange.parse (file:///home/martin/.cache/deno/npm/registry.npmjs.org/ssh2/1.15.0/lib/protocol/kex.js:1267:23)
    at Protocol.onKEXPayload (file:///home/martin/.cache/deno/npm/registry.npmjs.org/ssh2/1.15.0/lib/protocol/kex.js:1826:20)
    at NullDecipher.decrypt (file:///home/martin/.cache/deno/npm/registry.npmjs.org/ssh2/1.15.0/lib/protocol/crypto.js:612:26)
    at Protocol.parsePacket [as _parse] (file:///home/martin/.cache/deno/npm/registry.npmjs.org/ssh2/1.15.0/lib/protocol/Protocol.js:2028:25)
    at Protocol.parse (file:///home/martin/.cache/deno/npm/registry.npmjs.org/ssh2/1.15.0/lib/protocol/Protocol.js:313:16)
    at Socket.<anonymous> (file:///home/martin/.cache/deno/npm/registry.npmjs.org/ssh2/1.15.0/lib/client.js:775:21)
    at Socket.emit (ext:deno_node/_stream.mjs:1851:9)
    at addChunk (ext:deno_node/_stream.mjs:2873:16)
    at readableAddChunk (ext:deno_node/_stream.mjs:2852:13)"}

I am able to connect to the SFTP server via sftp client (see FileZilla screenshot below)
image

Code sample

import Client from "npm:ssh2-sftp-client@10.0.3";
export default async function (){

    let sftp = new Client();
    let pem_key = GetPemKey();
    
    const config = {
        host: '127.0.0.1',
        port: '22',
        username: 'username',
        privateKey: pem_key
    };

    config.debug = msg => {
        console.log(msg);
    };

    sftp.connect(config)
        .then(() => {
            console.log("connected!");
        });
}
@lucacasonato lucacasonato added bug Something isn't working correctly node compat crypto Related to node:crypto or WebCrypto labels Jun 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working correctly crypto Related to node:crypto or WebCrypto node compat
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants