loadPrivateKeyFromPpk static method

Uint8List loadPrivateKeyFromPpk(
  1. String? ppkFileContent, {
  2. String? password,
})

This helper method takes a ppkFileContent and its password and extracts the private key into a list.

Implementation

static Uint8List loadPrivateKeyFromPpk(String? ppkFileContent,
    {String? password}) {
  if (ppkFileContent == null) {
    throw Exception(
        'There is no file content provided to load a private key from!');
  }

  var encrypted = false;
  var endOfHeader = false;
  var publicKeyIndex = 0;
  var privateKeyIndex = 0;
  var publicKey = '';
  var privateKey = '';
  String? privateMac;
  var lines = ppkFileContent.split('\n');
  var macData = PpkMacData();
  for (var line in lines) {
    if (!endOfHeader) {
      if (lines.indexOf(line) == 0 &&
          !line.startsWith('PuTTY-User-Key-File-')) {
        throw Exception('File is no valid putty ssh-2 key file!');
      }
      if (line.startsWith('PuTTY-User-Key-File-')) {
        if (!line.startsWith('PuTTY-User-Key-File-2')) {
          throw Exception('Unsupported ssh-2 key file version!');
        }
        if (!line.trimRight().endsWith('ssh-ed25519')) {
          throw Exception(
              'The putty key has the wrong encryption method, use ssh-ed25519!');
        }
        macData.algorithm = 'ssh-ed25519';
      }
      if (line.startsWith('Encryption')) {
        if (!line.trimRight().endsWith('none')) {
          if (!line.trimRight().endsWith('aes256-cbc')) {
            throw Exception(
                'Unknown or unsupported putty file encryption! Supported values are "none" and "aes256-cbc"');
          }
          encrypted = true;
        }
        macData.encryption = line.split(': ')[1].trimRight();
      }
      if (line.startsWith('Comment')) {
        macData.comment = line.split(': ')[1].trimRight();
      }
      if (line.startsWith('Public-Lines')) {
        endOfHeader = true;
        publicKeyIndex = int.parse(line.split(': ')[1].trimRight());
        continue;
      }
    } else if (line.startsWith('Private-Lines')) {
      privateKeyIndex = int.parse(line.split(': ')[1].trimRight());
    } else if (publicKeyIndex > 0) {
      publicKey += line.trimRight();
      publicKeyIndex--;
    } else if (privateKeyIndex > 0) {
      privateKey += line.trimRight();
      privateKeyIndex--;
    } else if (line.startsWith('Private-MAC')) {
      privateMac = line.split(': ')[1].trimRight();
    }
  }
  macData.publicKey = base64.decode(publicKey);
  if (privateKey.isNotEmpty) {
    Uint8List privateKeyDecrypted;
    if (encrypted) {
      if (password == null || password.isEmpty) {
        throw Exception('No or empty password provided!');
      }
      privateKeyDecrypted =
          decodePpkPrivateKey(base64.decode(privateKey), password);
    } else {
      privateKeyDecrypted = base64.decode(privateKey);
    }
    macData.privateKey = privateKeyDecrypted;
    ppkMacCheck(privateMac, macData, password);
    return privateKeyDecrypted.sublist(4, 36);
  } else {
    throw Exception('Wrong file format. Could not extract a private key');
  }
}