import 'dart:convert'; import 'dart:math'; import 'dart:typed_data'; import 'package:gitjournal/ssh/binary_length_value.dart'; import 'package:steel_crypt/PointyCastleN/key_generators/rsa_key_generator.dart'; import 'package:steel_crypt/PointyCastleN/pointycastle.dart'; import 'package:steel_crypt/PointyCastleN/random/fortuna_random.dart'; import 'package:steel_crypt/steel_crypt.dart'; import 'package:meta/meta.dart'; import 'package:ssh_key/ssh_key.dart' as ssh_key; class RsaKeyPair { RSAPublicKey publicKey; RSAPrivateKey privateKey; RsaKeyPair.fromStrings({ @required String privateKey, @required String publicKey, }) { var encrypter = RsaCrypt(); publicKey = publicKey.trim(); try { var key = ssh_key.publicKeyDecode(publicKey); if (key is ssh_key.RSAPublicKeyWithInfo) { this.publicKey = RSAPublicKey(key.modulus, key.exponent); } } catch (e) { // Ignore } if (publicKey == null) { try { this.publicKey = encrypter.parseKeyFromString(publicKey); } catch (e) { // Ignore } } try { this.privateKey = encrypter.parseKeyFromString(privateKey); } catch (e) { // Ignore } } RsaKeyPair.generate() { var keyPair = _getRsaKeyPair(_getSecureRandom()); publicKey = keyPair.publicKey as RSAPublicKey; privateKey = keyPair.privateKey as RSAPrivateKey; } // Tries to encrypt and decrypt bool isValid() { var encrypter = RsaCrypt(); var orig = 'word'; var enc = encrypter.encrypt(orig, publicKey); var dec = encrypter.decrypt(enc, privateKey); return orig == dec; } // OpenSSH Public Key (single-line format) String publicKeyString({String comment = ""}) { var data = BinaryLengthValue.encode([ BinaryLengthValue.fromString("ssh-rsa"), BinaryLengthValue.fromBigInt(publicKey.exponent), BinaryLengthValue.fromBigInt(publicKey.modulus), ]); if (comment.isNotEmpty) { comment = comment.replaceAll('\r', ' '); comment = comment.replaceAll('\n', ' '); comment = ' $comment'; } return 'ssh-rsa ${base64.encode(data)}$comment'; } String privateKeyString() { var encrypter = RsaCrypt(); return encrypter.encodeKeyToString(privateKey); } } SecureRandom _getSecureRandom() { final secureRandom = FortunaRandom(); final random = Random.secure(); var seeds = List.of([]); for (var i = 0; i < 32; i++) { seeds.add(random.nextInt(255)); } secureRandom.seed(KeyParameter(Uint8List.fromList(seeds))); return secureRandom; } ///Create RSA keypair given SecureRandom. AsymmetricKeyPair _getRsaKeyPair( SecureRandom secureRandom, ) { // See URL for why these values // https://crypto.stackexchange.com/questions/15449/rsa-key-generation-parameters-public-exponent-certainty-string-to-key-count/15450#15450?newreg=e734eafab61e42f1b155b62839ccce8f final rsapars = RSAKeyGeneratorParameters(BigInt.from(65537), 2048 * 2, 5); final params = ParametersWithRandom(rsapars, secureRandom); final keyGenerator = RSAKeyGenerator(); keyGenerator.init(params); return keyGenerator.generateKeyPair(); }