Re: Keep number of rounds when changing passphrase or comment in private keep file

[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

 



Hi,

And by the way, I created a small python script to partialy parse the
private key file (new format) to be able to verify that my patch is
working correctly.

Here is the script attached.

Just run it with the private key file in argument:

$ prog/parse_openssh_keys.py test
ciphername: aes256-ctr
kdfname: bcrypt
rounds: 16
salt: d2b48709d4363adedc0ceb698916bc93
nkeys: 1
public_key len: 51
encrypted_len: 160

Hope it helps

Best regards

Loïc

On 09/04/2020, Loïc wrote :
> Hi,
>
> In ssh-keygen, if I set the number of rounds to a non default value
> using -a option and then change the passphrase or the comment:
>
> $ ssh-keygen -t ed25519 -Pfoobar -a 100 -f test
> $ ssh-keygen -c -C "foobar comment" -Pfoobar -f test
>
> The number of rounds is reset to the default value.
>
> I find this annoying because if I set the number of rounds to a given
> high number for security, I don't want it to be reduce behind my back
> when I change the passphrase or the comment.
>
>
> So, I have created patches to change this and make sure the number of
> rounds is preserved if it is not forced when changing the comment or
> passphrase.
>
> I will send them in the following emails. There are based on the
> portable git (|https://anongit.mindrot.org/openssh.git).|
>
> I'm open to your comments (in particular, I'm not pleased with the name
> of the struct sshkey_vault). Also, I'm wondering if the comment itself
> shouldn't be move to this structure.
>
> Also, I'm considering to add more field to this structure, like the salt
> and cypher, in order to add a feature that display the information about
> the keyfile (type, cypher type, key derivation type, number of rounds,
> comment...)
>
> Thank you
>
> Best regards
>
> Loïc
>
> _______________________________________________
> openssh-unix-dev mailing list
> openssh-unix-dev@xxxxxxxxxxx
> https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

MARK_BEGIN  = "-----BEGIN OPENSSH PRIVATE KEY-----\n"
MARK_END    = "-----END OPENSSH PRIVATE KEY-----\n"

openssh_magic = b"openssh-key-v1\x00"

from base64 import b64decode

import struct
def parse_cstring(data, pos):
    pos, byte = parse_bytes(data, pos)
    return (pos, byte.decode())

def parse_bytes(data, pos):
    length = int.from_bytes(data[pos:pos+4], byteorder='big', signed=False)
    assert(len(data) >= pos+4+length)
    ans = data[pos+4:pos+4+length]
    return (pos+length+4, ans)

def parse_u32(data, pos):
    ans = int.from_bytes(data[pos:pos+4], byteorder='big', signed=False)
    return (pos+4, ans)

def parse(filename):
    with open(filename) as f:
        data = f.read()
        if data.startswith(MARK_BEGIN) \
            and data.endswith(MARK_END):
            data = data[len(MARK_BEGIN):-len(MARK_END)-1]
            data = b64decode(data)
            # OpenSSH format:
            # AUTH_MAGIC "openssh-key-v1" (nul terminated)
            # ciphername    cstring (32-bit len (BE), string)
            # kdfname       cstring (32-bit len, string)
            #                   only "none" and "bcrypt" known
            # kdf           bstring (32-bit len, )
            #    salt       bstring (32-bit len, bytes)
            #    rounds     u32 (BE)
            # nkeys         u32 (BE) (must be 1)
            # pubkey        bstring
            # encrypted_len u32
            # 
            if not data.startswith(openssh_magic):
                print("OpenSSH private key file but uknown version: {}".format(data[:len(openssh_magic)]))
                return
            pos = len(openssh_magic)
            pos, ciphername = parse_cstring(data, pos)
            print("ciphername: {}".format(ciphername))
            pos, kdfname = parse_cstring(data, pos)
            print("kdfname: {}".format(kdfname))
            pos, kdf = parse_bytes(data, pos)
            if kdfname != "none":
                pos_kdf = 0
                pos_kdf, salt = parse_bytes(kdf, pos_kdf)
                pos_kdf, rounds = parse_u32(kdf, pos_kdf)
                print("rounds: {}".format(rounds))
                print("salt: {}".format(salt.hex()))
            pos, nkeys = parse_u32(data, pos)
            print("nkeys: {}".format(nkeys))
            pos, public_key = parse_bytes(data, pos)
            print("public_key len: {}".format(len(public_key)))
            pos, encrypted_len = parse_u32(data, pos)
            print("encrypted_len: {}".format(encrypted_len))
            # aes256-ctr keylen=32, blocksize=16, ivlen=16
        else:
            print("ERROR: \"{}\" is not an OpenSSH private file".format(filename))
    return

if __name__ == "__main__":
    import sys
    parse(sys.argv[1])
_______________________________________________
openssh-unix-dev mailing list
openssh-unix-dev@xxxxxxxxxxx
https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev

[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux