digitalbazaar / forge

A native implementation of TLS in Javascript and tools to write crypto-based and network-heavy webapps
https://digitalbazaar.com/
Other
5.04k stars 778 forks source link

Putty Private Key generated by SSH is not always valid. #952

Open yammelvin opened 2 years ago

yammelvin commented 2 years ago

I wrote a test node js script to do the following:

  1. generate a rsa key pair
  2. using the generated rsa private key, generate the putty private key using forge
  3. using the same generated rsa private key, generate the putty private key using the 'puttygen' command line.
  4. compare the two putty private keys.

Out of every 100 times, about 7 to 10 times the ppk generated is not the same. When it is not the same, the ppk by forge cannot be loaded or used by putty, however the ppk by puttygen is ok.

Attached is the test script.

testforgeputty.zip

mathieucaroff commented 1 year ago

@yammelvin

I've tried to run the test script, but I ran into issue with the puttygen parameters -C and -O

The documentation I've found for PuTTYgen does not mention these parameters either:

https://tartarus.org/~simon/putty-snapshots/htmldoc/Chapter8.html#puttygen-cli

The options supported on the command line are:

-t keytype Type of key to generate. You can select rsa, dsa, ecdsa, eddsa, ed25519, ed448, or rsa1. See section 8.2.2. -b bits Size of the key to generate, in bits. See section 8.2.3. --primes method Method for generating prime numbers. You can select probable, proven, and proven-even. See section 8.2.4. --strong-rsa When generating an RSA key, make sure the prime factors of the key modulus are ‘strong primes’. See section 8.2.4. --ppk-param key=value,... Allows setting all the same details of the PPK save file format described in section 8.2.13.

yammelvin commented 1 year ago

@mathieucaroff

I am using puttygen release 0.78 on Ubuntu 22.04 LTS. Perhaps you are using an old version?

The official website is https://www.puttygen.com/#Download_PuTTYgen_for_UbuntuLinux -C and -O are valid options as stated in the website.

The following are the outputs of puttygen and -C and -O are definitely valid options.

> puttygen
Usage: puttygen ( keyfile | -t type [ -b bits ] )
                [ -C comment ] [ -P ] [ -q ]
                [ -o output-keyfile ] [ -O type | -l | -L | -p ]
Use "puttygen --help" for more detail.
> puttygen --help
PuTTYgen: key generator and converter for the PuTTY tools
Release 0.78
Usage: puttygen ( keyfile | -t type [ -b bits ] )
                [ -C comment ] [ -P ] [ -q ]
                [ -o output-keyfile ] [ -O type | -l | -L | -p ]
  -t    specify key type when generating:
           eddsa, ecdsa, rsa, dsa, rsa1   use with -b
           ed25519, ed448                 special cases of eddsa
  -b    specify number of bits when generating key
  -C    change or specify key comment
  -P    change key passphrase
  -q    quiet: do not display progress bar
  -O    specify output type:
           private             output PuTTY private key format
           private-openssh     export OpenSSH private key
           private-openssh-new export OpenSSH private key (force new format)
           private-sshcom      export ssh.com private key
           public              RFC 4716 / ssh.com public key
           public-openssh      OpenSSH public key
           fingerprint         output the key fingerprint
           cert-info           print certificate information
           text                output the key components as 'name=0x####'
  -o    specify output file
  -l    equivalent to `-O fingerprint'
  -L    equivalent to `-O public-openssh'
  -p    equivalent to `-O public'
  --cert-info   equivalent to `-O cert-info'
  --dump   equivalent to `-O text'
  -E fptype            specify fingerprint output type:
                          sha256, md5, sha256-cert, md5-cert
  --certificate file   incorporate a certificate into the key
  --remove-certificate remove any certificate from the key
  --reencrypt          load a key and save it with fresh encryption
  --old-passphrase file
        specify file containing old key passphrase
  --new-passphrase file
        specify file containing new key passphrase
  --random-device device
        specify device to read entropy from (e.g. /dev/urandom)
  --primes <type>      select prime-generation method:
        probable       conventional probabilistic prime finding
        proven         numbers that have been proven to be prime
        proven-even    also try harder for an even distribution
  --strong-rsa         use "strong" primes as RSA key factors
  --ppk-param <key>=<value>[,<key>=<value>,...]
        specify parameters when writing PuTTY private key file format:
            version       PPK format version (min 2, max 3, default 3)
            kdf           key derivation function (argon2id, argon2i, argon2d)
            memory        Kbyte of memory to use in passphrase hash
                             (default 8192)
            time          approx milliseconds to hash for (default 100)
            passes        number of hash passes to run (alternative to 'time')
            parallelism   number of parallelisable threads in the hash function
                             (default 1)
yammelvin commented 1 year ago

@mathieucaroff

At the time of writing the test script. I was using puttygen 0.76 which by default generates ppk version 2. I just rerun the script using puttygen 0.78 which by default generates ppk version 3. With puttygen 0.78, you need to add the option --ppk-param version=2 to generate ppk version 2.

Attached is the updated test script for putty 0.78. testforgeputty.zip

In any case, node-forge generates ppk version 2 which is obsolete. putty now uses ppk version 3.