Flutter SSH连接管理插件ssh_key的使用

发布于 1周前 作者 phonegap100 来自 Flutter

Flutter SSH连接管理插件ssh_key的使用

简介

ssh_key 是一个用于编码和解码不同文本文件格式中的公钥和私钥的Dart库。这个库主要用于SSH实现中使用的文件格式,但也支持其他程序使用的某些格式。本文将详细介绍如何在Flutter项目中使用 ssh_key 插件进行SSH连接管理。

支持的格式

公钥格式

  • OpenSSH Public Key:旧版本OpenSSH使用的单行格式。
  • SSH Public Key:由RFC 4716定义并被新版本OpenSSH使用。
  • Textual encoding of PKCS #1:OpenSSH称之为“PEM”,这是一个模糊的术语。
  • Textual encoding of subjectPublicKeyInfo from X.509:OpenSSH错误地将其称为“PKCS #8”。

私钥格式

  • OpenSSH Private Key
  • PuTTY Private Key (PPK)
  • Textual encoding of PKCS #1

示例代码

以下是一个完整的示例代码,展示了如何在Flutter项目中使用 ssh_key 插件来解析和编码公钥和私钥。

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

void processPublic(String str, bool verbose, ssh_key.PubKeyEncoding? format) {
  // 解码公钥
  final pubKey = ssh_key.publicKeyDecode(str);

  // 输出公钥中的值
  if (verbose) {
    if (pubKey is ssh_key.RSAPublicKeyWithInfo) {
      // 使用RSA公钥
      stderr.write('''
RSA public key:
  modulus: ${pubKey.n}
  public exponent: ${pubKey.publicExponent}
  fingerprint: ${pubKey.fingerprint()}
''');
    } else {
      stderr.writeln('Error: recognised public key, but not RSA');
      exit(1);
    }
  }

  // 编码公钥
  if (format != null) {
    final destEncoding = pubKey.encode(format);
    stdout.write(destEncoding);
  }
}

void processPrivate(String str, bool verbose, ssh_key.PvtKeyEncoding? format) {
  // 解码私钥
  final privateKey = ssh_key.privateKeyDecode(str);

  // 输出私钥中的值
  if (verbose) {
    if (privateKey is ssh_key.RSAPrivateKeyWithInfo) {
      // 使用RSA私钥
      stderr.write('''
RSA private key:
  modulus: ${privateKey.modulus}
  public exponent: ${privateKey.publicExponent}
  private exponent: ${privateKey.privateExponent}
  prime1 (p): ${privateKey.p}
  prime2 (q): ${privateKey.q}
''');
    } else {
      stderr.writeln('Error: recognised private key, but not RSA');
      exit(1);
    }
  }

  // 编码私钥
  if (format != null) {
    final destEncoding = privateKey.encode(format);
    stdout.write(destEncoding);
  }
}

class Options {
  Options(List<String> args) {
    bool showHelp = false;
    String? outputFormatArg;
    final filenames = <String>[];

    for (final arg in args) {
      if (arg.startsWith('-')) {
        switch (arg) {
          case '--public':
            isPublic = true;
            break;
          case '--private':
          case '--secret':
          case '-s':
            isPublic = false;
            break;
          case '--verbose':
          case '-v':
            verbose = true;
            break;
          case '--help':
          case '-h':
            showHelp = true;
            break;
          case '--openssh':
          case '--sshpublickey':
          case '--pkcs1':
          case '--x509spki':
          case '--puttyprivatekey':
            outputFormatArg = arg;
            break;
          default:
            stderr.write('Usage error: unknown option: $arg (-h for help)\n');
            exit(2);
        }
      } else {
        filenames.add(arg);
      }
    }

    if (filenames.isEmpty) {
      stderr.write('Usage error: missing filename (-h for help)\n');
      exit(2);
    } else if (filenames.length == 1) {
      filename = filenames.first;
    } else {
      stderr.write('Usage error: too many arguments (-h for help)\n');
      exit(2);
    }

    if (isPublic) {
      if (outputFormatArg != null) {
        publicKeyOutFormat = {
          '--openssh': ssh_key.PubKeyEncoding.openSsh,
          '--sshpublickey': ssh_key.PubKeyEncoding.sshPublicKey,
          '--pkcs1': ssh_key.PubKeyEncoding.pkcs1,
          '--x509spki': ssh_key.PubKeyEncoding.x509spki,
        }[outputFormatArg];
        if (publicKeyOutFormat == null) {
          stderr.writeln('Error: $outputFormatArg not for a public key');
          exit(2);
        }
      }
    } else {
      if (outputFormatArg != null) {
        privateKeyOutFormat = {
          '--openssh': ssh_key.PvtKeyEncoding.openSsh,
          '--puttyprivatekey': ssh_key.PvtKeyEncoding.puttyPrivateKey,
          '--pkcs1': ssh_key.PvtKeyEncoding.pkcs1,
        }[outputFormatArg];
        if (privateKeyOutFormat == null) {
          stderr.writeln('Error: $outputFormatArg not for a private key');
          exit(2);
        }
      }
    }

    if (showHelp) {
      stderr.write('''
Usage: example [options] filename
Options:
  --public    file contains a public key (default)
  --private   file contains a private key
  --verbose   show the key parameters

Output format for public keys:  
  --openssh       old OpenSSH public key format (one line)
  --sshpublickey  new OpenSSH public key format (RFC 4716)
  --pkcs1         PKCS#1 public key format
  --x509spki      X.509 SubjectPublicKeyInformation (incorrectly called PKCS#8)

Output format for private keys only:
  --openssh          OpenSSH format (old format)
  --puttyprivatekey  PuTTY Private Key (PPK) format
  --pkcs1            PKCS#1 private key format
''');
      exit(0);
    }
  }

  bool isPublic = true;
  late String filename;

  bool verbose = false;

  ssh_key.PubKeyEncoding? publicKeyOutFormat;
  ssh_key.PvtKeyEncoding? privateKeyOutFormat;
}

void main(List<String> args) {
  // 解析命令行参数
  final options = Options(args);

  // 读取文件内容
  final srcEncoding = File(options.filename).readAsStringSync();

  // 解析内容并输出结果
  if (options.isPublic) {
    processPublic(srcEncoding, options.verbose, options.publicKeyOutFormat);
  } else {
    processPrivate(srcEncoding, options.verbose, options.privateKeyOutFormat);
  }
}

已知限制

  • 仅支持RSA密钥:目前只支持RSA密钥的完整解析和编码。
  • Dart版本要求:需要Dart 2.7.0或更高版本,因为该库使用了Dart的扩展方法。
  • 私钥支持实验性:私钥的支持还处于实验阶段,互操作性可能无法保证。
  • 不支持加密私钥:受密码保护的私钥不被支持。

总结

ssh_key 插件为Flutter开发者提供了强大的工具来处理各种SSH密钥格式。通过上述示例代码,您可以轻松地在Flutter项目中集成SSH密钥的解析和编码功能。希望这篇文章能帮助您更好地理解和使用 ssh_key 插件。


更多关于Flutter SSH连接管理插件ssh_key的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter SSH连接管理插件ssh_key的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter应用中使用ssh_key插件来管理SSH连接的示例代码。这个示例将展示如何配置和使用SSH密钥来连接到远程服务器。

首先,确保你已经在你的pubspec.yaml文件中添加了ssh_key插件的依赖项:

dependencies:
  flutter:
    sdk: flutter
  ssh_key: ^x.y.z  # 请替换为最新版本号

然后,运行flutter pub get来安装依赖项。

以下是一个完整的示例,展示了如何使用ssh_key插件:

import 'package:flutter/material.dart';
import 'package:ssh_key/ssh_key.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String result = "";

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('SSH连接管理'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text('SSH连接结果:'),
              Text(result, style: TextStyle(fontSize: 18)),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: _connectToSSH,
                child: Text('连接到SSH'),
              ),
            ],
          ),
        ),
      ),
    );
  }

  void _connectToSSH() async {
    // 远程服务器信息
    String hostname = "your.remote.server";
    int port = 22;
    String username = "your_username";
    
    // 私钥路径(可以是本地路径,也可以是内嵌的私钥字符串)
    // 注意:为了安全起见,通常不建议在代码中硬编码私钥
    String privateKeyPath = "/path/to/your/private/key";
    // String privateKey = "-----BEGIN PRIVATE KEY-----\n...your private key...\n-----END PRIVATE KEY-----";

    // 初始化SSH客户端
    SSHClient ssh = SSHClient();

    try {
      // 使用私钥进行身份验证
      await ssh.connect(
        hostname: hostname,
        port: port,
        username: username,
        privateKey: privateKeyPath // 如果使用字符串私钥,则使用 privateKey: privateKey
      );

      // 执行远程命令
      String command = "ls -la";
      String output = await ssh.execCommand(command);

      // 更新UI
      setState(() {
        result = output;
      });

      // 断开连接
      await ssh.disconnect();
    } catch (e) {
      // 处理错误
      setState(() {
        result = "连接失败: ${e.message}";
      });
    }
  }
}

注意事项:

  1. 私钥安全:在实际应用中,不要在代码中硬编码私钥。你可以考虑使用安全的密钥管理服务,或者在用户设备上安全地存储密钥。

  2. 错误处理:在生产代码中,应该有更详细的错误处理逻辑,以处理各种可能的异常情况。

  3. 权限:确保应用有权限访问私钥文件(如果是从文件系统加载私钥)。

  4. 插件版本:确保你使用的是ssh_key插件的最新版本,并查看其文档以获取最新的API和用法。

这个示例演示了基本的SSH连接管理,包括如何连接到远程服务器、执行命令以及断开连接。你可以根据需要扩展这个示例,以满足你的具体需求。

回到顶部