ssh_key 0.5.0

ssh_key #

Encodes and decodes keys to/from different text file formats.

Introduction #

This package allows public keys and private keys to be decoded from different text file formats. And for them to be encoded into those formats.

The primary focus is on the file formats used by implementations of SSH. But some of these formats are also used by other programs; and there is no fundamental reason why other key file formats can't be supported.

SSH implementations use a number of different file formats to represent public-keys. While the SSH wire-protocol is standardized, the storage of keys was an implementation detail that was left undefined. Consequently, different implementations have used different (often proprietary) file formats to store their keys.

Formats #

These public key formats are supported:

  • OpenSSH Public Key (single-line format)

  • SSH Public Key (defined by RFC 4716, sometimes called "SSH2")

  • Textual encoding of PKCS #1 (OpenSSH calls this "PEM")

  • Textual encoding of subjectPublicKeyInfo from X.509 (OpenSSH incorrectly calls this "PKCS #8")

Public-key algorithms #

This public-key algorithm is supported:

  • RSA

Example #

import 'dart:io';
import 'package:ssh_key/ssh_key.dart' as ssh_key;

void main(List<String> args) {
  final filename = args[0];
  final outputFormat = ssh_key.PubKeyEncoding.sshPublicKey;
  // final outputFormat = ssh_key.PubKeyEncoding.openSSH;
  // final outputFormat = ssh_key.PubKeyEncoding.pkcs1;
  // final outputFormat = ssh_key.PubKeyEncoding.x509spki;

  // Read the file and decoding it

  final srcEncoding = File(filename).readAsStringSync();

  final pubKey = ssh_key.publicKeyDecode(srcEncoding);

  if (pubKey is ssh_key.RSAPublicKeyWithInfo) {
    // Use the RSA public key (this example just prints it out)

    stderr.write('''RSA public key:
  fingerprint: ${pubKey.fingerprint()}
  modulus: ${pubKey.n}
  public exponent: ${pubKey.e}
''');
    // The modulus and public exponent (n and e) are available,
    // because the RSAPublicKeyWithInfo is a subclass of the
    // Pointy Castle RSAPublicKey class.
  }

  // Encode the public key and printing it out

  final destEncoding = pubKey.encode(outputFormat);

  stdout.write(destEncoding);
}

Know limitations #

  • Only RSA keys are supported.

  • Requires Dart 2.7.0 or later, because it uses Dart extension methods to make the encode method to available on the Pointy Castle public and private key classes.

  • Private key support is experimental and only supports private keys that have not been protected by a passphrase. Private key formats:

    • PKCS #1 (as used by OpenSSH)
    • PuTTY Private Key (.PPK)

This package uses the public-key classes from the Pointy Castle package. Mainly because it has classes to represent RSA keys, and implements symmetric encryption algorithms (which will be needed when support for encrypted private keys is added). In theory, this package could have been independent of any cryptographic package, but it would then have to implement its own classes for reprsenting the keys.

Note: support for other formats is limited by the lack of documentation about the format (since they are often proprietary). Support for other types of keys is limited by the implementation of other cryptographic algorithms in Dart.

Which library to use #

Three libraries are provided by this package.

Most programs should only need to use the ssh_key library. The other two libraries are for internal use by the ssh_key library.

import 'package:ssh_key/ssh_key.dart' as ssh_key;

Changelog #

0.5.0 #

  • Initial release.

example/example.dart

#!/usr/bin/env dart
//
// Example from README.md file.
//
// Example:
//
//     dart example.dart test-rsa-key.pem

import 'dart:io';
import 'package:ssh_key/ssh_key.dart' as ssh_key;

void main(List<String> args) {
  if (args.isEmpty) {
    stderr.write('Usage error: missing public key filename\n');
    exit(1);
  }
  if (1 < args.length) {
    stderr.write('Usage error: too many arguments\n');
    exit(1);
  }

  final filename = args[0];
  final outputFormat = ssh_key.PubKeyEncoding.sshPublicKey;
  // final outputFormat = ssh_key.PubKeyEncoding.openSSH;
  // final outputFormat = ssh_key.PubKeyEncoding.pkcs1;
  // final outputFormat = ssh_key.PubKeyEncoding.x509spki;

  // Read the file and decoding it

  final srcEncoding = File(filename).readAsStringSync();

  final pubKey = ssh_key.publicKeyDecode(srcEncoding);

  if (pubKey is ssh_key.RSAPublicKeyWithInfo) {
    // Use the RSA public key (this example just prints it out)

    stderr.write('''RSA public key:
  fingerprint: ${pubKey.fingerprint()}
  modulus: ${pubKey.n}
  public exponent: ${pubKey.e}
''');
    // The modulus and public exponent (n and e) are available,
    // because the RSAPublicKeyWithInfo is a subclass of the
    // Pointy Castle RSAPublicKey class.
  }

  // Encode the public key and printing it out

  final destEncoding = pubKey.encode(outputFormat);

  stdout.write(destEncoding);
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  ssh_key: ^0.5.0

2. Install it

You can install packages from the command line:

with pub:


$ pub get

with Flutter:


$ flutter pub get

Alternatively, your editor might support pub get or flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:ssh_key/ssh_key.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
25
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
90
Overall:
Weighted score of the above. [more]
60
Learn more about scoring.

We analyzed this package on Feb 12, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.7.1
  • pana: 0.13.5

Health suggestions

Fix lib/src/keys/rsa.dart. (-0.50 points)

Analysis of lib/src/keys/rsa.dart reported 1 hint:

line 525 col 9: The value of the local variable 'prefix' isn't used.

Maintenance issues and suggestions

Support latest dependencies. (-10 points)

The version constraint in pubspec.yaml does not support the latest published versions for 1 dependency (asn1lib).

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.7.0 <3.0.0
asn1lib ^0.5.14 0.5.15 0.6.0
pointycastle ^1.0.2 1.0.2
tuple ^1.0.1 1.0.3
Transitive dependencies
matcher 0.12.6
meta 1.1.8
path 1.6.4
quiver 2.1.2+1
stack_trace 1.9.3
Dev dependencies
test ^1.9.4