0

I'm trying to implement the putty file format in one of my dart packages. Implementing the actual key loading was ok, but I'm struggeling with the mac validation. I'm not shure what I'm doing wrong here

The putty code is quite clear about how to check it, but something is still wrong here. The putty code generates the validating mac like this:

hash = ssh_hash_new(&ssh_sha1);
put_data(hash, header, sizeof(header)-1);
if (cipher && passphrase)
put_data(hash, passphrase, passlen);
ssh_hash_final(hash, mackey);

mac = ssh2_mac_new(&ssh_hmac_sha1, NULL);
ssh2_mac_setkey(mac, make_ptrlen(mackey, 20));
ssh2_mac_start(mac);
put_data(mac, macdata->s, macdata->len);
ssh2_mac_genresult(mac, binary);
ssh2_mac_free(mac);

my dart code does it like this:

var sha1Hash = SHA1Digest()
               ..update(Uint8List.fromList("putty-private-key-file-mac-key".codeUnits), 0, "putty-private-key-file-mac-key".codeUnits.length);
if (password != null) {
    sha1Hash.update(Uint8List.fromList(password.codeUnits), 0, password.codeUnits.length);
}
var key = Uint8List(20);
sha1Hash.doFinal(key, 0);

var macResult = Uint8List(20);
var mac = HMac(SHA1Digest(), 64);
mac.init(KeyParameter(key));
mac.update(Uint8List.fromList(macData.codeUnits), 0, macData.codeUnits.length);
mac.doFinal(macResult, 0);

I'm pretty sure that the first part of creating the key for the mac is correct, because the same code is used to decrypt the private key and it works as expected. I'm not sure about the second part of creating the actual MAC.

Maybe my algorithm is right an I'm doing something else wrong? To check that in depth it would be nice if someone could provide me with a testvector containing:

  • ppkFileContent
  • password
  • macData
  • key

1 Answers1

0

This is a valid test vector

file content:

PuTTY-User-Key-File-2: ssh-ed25519
Encryption: aes256-cbc
Comment: ed25519-key-20210211
Public-Lines: 2
AAAAC3NzaC1lZDI1NTE5AAAAIHOsd4LSZlb3xokKjybt5q1CxL3gHmqhNmaOaCNM
X43n
Private-Lines: 1
b6LQNEHpLzACUyQLVAsbRUnKlKUVCfFEZGq5DcrAgOd8cm4EVPrdOoGrAeeJs8Av
Private-MAC: 7ee3b96fa12f4f9bb12df5c3ccccc0a4eddfd8b3

password: password

mac data:

{
    "algorithm": "ssh-ed25519",
    "encryption": "aes256-cbc",
    "comment": "ed25519-key-20210211",
    "publicKey": [0, 0, 0, 11, 115, 115, 104, 45, 101, 100, 50, 53, 53, 49, 57, 0, 0, 0, 32, 115, 172, 119, 130, 210, 102, 86, 247, 198, 137, 10, 143, 38, 237, 230, 173, 66, 196, 189, 224, 30, 106, 161, 54, 102, 142, 104, 35, 76, 95, 141, 231],
    "privateKey": [0, 0, 0, 32, 141, 73, 118, 119, 135, 33, 122, 2, 181, 240, 18, 204, 171, 163, 81, 33, 160, 138, 171, 176, 50, 73, 106, 3, 203, 14, 219, 151, 10, 35, 60, 212, 221, 202, 157, 227, 53, 116, 1, 82, 247, 119, 115, 198]
}

HMac-SHA-256 key:

[20, 182, 90, 180, 82, 65, 198, 109, 180, 232, 79, 25, 125, 194, 202, 107, 75, 170, 62, 210]

MAC: "7ee3b96fa12f4f9bb12df5c3ccccc0a4eddfd8b3"

What is somewhat not quite well documented is the fact that you need to add the lengths for each field to the mac. You can see this in my code.