From 96656ec79201b545d3571a025c368655a4805726 Mon Sep 17 00:00:00 2001 From: olegkap_cp Date: Thu, 16 Dec 2010 18:17:05 +0000 Subject: [PATCH] Minor changes to how PrivateKey file is parsed --- .../Renci.SshClient/PrivateKeyFile.cs | 103 +++++------------- .../Security/CryptoPrivateKey.cs | 7 -- .../Security/CryptoPrivateKeyDss.cs | 7 +- .../Security/CryptoPrivateKeyRsa.cs | 6 +- 4 files changed, 31 insertions(+), 92 deletions(-) diff --git a/Renci.SshClient/Renci.SshClient/PrivateKeyFile.cs b/Renci.SshClient/Renci.SshClient/PrivateKeyFile.cs index 87fd11bb..8260ea3b 100644 --- a/Renci.SshClient/Renci.SshClient/PrivateKeyFile.cs +++ b/Renci.SshClient/Renci.SshClient/PrivateKeyFile.cs @@ -1,18 +1,18 @@ using System; +using System.Linq; using System.Collections.Generic; using System.IO; using System.Text; using System.Text.RegularExpressions; using Renci.SshClient.Security; +using System.Security.Cryptography; +using System.Security; namespace Renci.SshClient { public class PrivateKeyFile { - private Regex _beginKeyLine = new Regex(@"----[ ]*BEGIN (?.+) PRIVATE KEY[ ]*----"); - private Regex _headerLine = new Regex(@"(?[^:]{1,64}):[ ](?[^:]+(?\\)?)"); - private Regex _headerLineContinue = new Regex(@"(?[^:]+(?\\)?)"); - private Regex _endKeyLine = new Regex(@"----[ ]*END (?.+) PRIVATE KEY[ ]*----"); + private static Regex _privateKeyRegex = new Regex(@"^-----BEGIN (?\w+) PRIVATE KEY-----\r\n(Proc-Type: 4,ENCRYPTED\r\nDEK-Info: (?[A-Z0-9-]+),(?[A-F0-9]{16})\r\n\r\n)?(?([a-zA-Z0-9/+=]{1,64}\r\n)+)-----END \k PRIVATE KEY-----.*", RegexOptions.Compiled | RegexOptions.Multiline); private CryptoPrivateKey _key; @@ -65,85 +65,40 @@ namespace Renci.SshClient private void Open(Stream privateKey, string passPhrase) { - var headerTag = string.Empty; - var headerValue = string.Empty; - var headerValueContinue = false; - var data = new StringBuilder(); - var keyName = string.Empty; - - var fileLine = string.Empty; + Match privateKeyMatch = null; using (StreamReader sr = new StreamReader(privateKey)) { - while ((fileLine = sr.ReadLine()) != null) - { - var match = _beginKeyLine.Match(fileLine); - if (match.Success) - { - keyName = match.Result("${keyName}"); - continue; - } - - match = _endKeyLine.Match(fileLine); - if (match.Success) - { - var endKeyName = match.Result("${keyName}"); - if (!endKeyName.Equals(keyName)) - throw new InvalidDataException("Invalid data key file."); - break; - } - - - // Ignore everything if BEGIN was not found yet - if (string.IsNullOrEmpty(keyName)) - { - continue; - } - - match = _headerLine.Match(fileLine); - if (match.Success) - { - headerTag = match.Result("${headerTag}"); - headerValue = match.Result("${headerValue}"); - if (match.Result("${continue}") == @"\") - { - headerValueContinue = true; - } - else - { - headerValueContinue = false; - } - continue; - } - - if (headerValueContinue) - { - headerValue += fileLine; - if (match.Result("${continue}") == @"\") - { - headerValueContinue = true; - } - else - { - headerValueContinue = false; - } - continue; - } - - data.Append(fileLine); - } + privateKeyMatch = _privateKeyRegex.Match(sr.ReadToEnd()); } - if (string.IsNullOrEmpty(keyName)) + if (!privateKeyMatch.Success) { - throw new InvalidDataException("Invalid Public key file"); + throw new InvalidDataException("Invalid private key file."); + } + + var keyName = privateKeyMatch.Result("${keyName}"); + var cryptName = privateKeyMatch.Result("${cryptName}"); + var salt = privateKeyMatch.Result("${salt}"); + var data = privateKeyMatch.Result("${data}"); + + var decryptedData = string.Join(string.Empty, data.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries)); + + if (!string.IsNullOrEmpty(cryptName) && !string.IsNullOrEmpty(salt)) + { + if (string.IsNullOrEmpty(passPhrase)) + throw new InvalidOperationException("Private key is encrypted but passphrase is empty."); + + var binaryKey = Convert.FromBase64String(passPhrase); + var binarySalt = Convert.FromBase64String(salt); + + throw new NotImplementedException(); } switch (keyName) { case "RSA": this._key = new CryptoPrivateKeyRsa(); - break; case "DSA": this._key = new CryptoPrivateKeyDss(); @@ -151,9 +106,9 @@ namespace Renci.SshClient default: throw new NotSupportedException(string.Format("Key '{0}' is not supported.", keyName)); } + var decrypted = System.Convert.FromBase64String(data); - this._key.Load(System.Convert.FromBase64String(data.ToString()), passPhrase); + this._key.Load(decrypted); } - } -} \ No newline at end of file +} diff --git a/Renci.SshClient/Renci.SshClient/Security/CryptoPrivateKey.cs b/Renci.SshClient/Renci.SshClient/Security/CryptoPrivateKey.cs index 12f930a5..5f6aa919 100644 --- a/Renci.SshClient/Renci.SshClient/Security/CryptoPrivateKey.cs +++ b/Renci.SshClient/Renci.SshClient/Security/CryptoPrivateKey.cs @@ -5,13 +5,6 @@ namespace Renci.SshClient.Security { public abstract class CryptoPrivateKey : CryptoKey { - public override void Load(IEnumerable data) - { - this.Load(data, null); - } - - public abstract void Load(IEnumerable data, string passPhrase); - public abstract CryptoPublicKey GetPublicKey(); public abstract IEnumerable GetSignature(IEnumerable key); diff --git a/Renci.SshClient/Renci.SshClient/Security/CryptoPrivateKeyDss.cs b/Renci.SshClient/Renci.SshClient/Security/CryptoPrivateKeyDss.cs index c5296c6e..c505624f 100644 --- a/Renci.SshClient/Renci.SshClient/Security/CryptoPrivateKeyDss.cs +++ b/Renci.SshClient/Renci.SshClient/Security/CryptoPrivateKeyDss.cs @@ -19,13 +19,8 @@ namespace Renci.SshClient.Security get { return "ssh-dss"; } } - public override void Load(IEnumerable data, string passPhrase) + public override void Load(IEnumerable data) { - if (passPhrase != null) - { - throw new NotSupportedException("Keys with passphrase currently not supported"); - } - MemoryStream ms = null; try { diff --git a/Renci.SshClient/Renci.SshClient/Security/CryptoPrivateKeyRsa.cs b/Renci.SshClient/Renci.SshClient/Security/CryptoPrivateKeyRsa.cs index 64d127da..ddd4f5a9 100644 --- a/Renci.SshClient/Renci.SshClient/Security/CryptoPrivateKeyRsa.cs +++ b/Renci.SshClient/Renci.SshClient/Security/CryptoPrivateKeyRsa.cs @@ -22,12 +22,8 @@ namespace Renci.SshClient.Security get { return "ssh-rsa"; } } - public override void Load(IEnumerable data, string passPhrase) + public override void Load(IEnumerable data) { - if (passPhrase != null) - { - throw new NotSupportedException("Keys with passphrase currently not supported"); - } MemoryStream ms = null; try {