Skip to content

Commit 987bea6

Browse files
committed
WIP: Support for Ed25519 Host- and Private-Keys
ToDo: OpenSSHKey-Reader needs crypto support
1 parent 712c677 commit 987bea6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+8272
-1
lines changed

src/Renci.SshNet.Tests/Classes/PrivateKeyFileTest.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,28 @@ public void Test_PrivateKey_ECDSA521_Encrypted()
385385
}
386386
}
387387

388+
[TestMethod]
389+
[Owner("darinkes")]
390+
[TestCategory("PrivateKey")]
391+
public void Test_PrivateKey_ED25519()
392+
{
393+
using (var stream = GetData("Key.ED25519.txt"))
394+
{
395+
new PrivateKeyFile(stream, "12345");
396+
}
397+
}
398+
399+
[TestMethod]
400+
[Owner("darinkes")]
401+
[TestCategory("PrivateKey")]
402+
public void Test_PrivateKey_ED25519_Encrypted()
403+
{
404+
using (var stream = GetData("Key.ED25519.Encrypted.txt"))
405+
{
406+
new PrivateKeyFile(stream, "12345");
407+
}
408+
}
409+
388410
/// <summary>
389411
///A test for Dispose
390412
///</summary>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
-----BEGIN OPENSSH PRIVATE KEY-----
2+
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABCziVlGog
3+
eUxEUKJcduOqCCAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIBZfAisK02MKZeSy
4+
MGo9lxq7Otgg1ll2Qhp+ySacRk2CAAAAoDc5MjTED1jcIotaaqc6DcnADwVnPf/4iC9BM2
5+
+2C+6uKXuYGOuqb16kFHn8yYAkABX2mtQo1GmJt5lPriMkJ1qNfZ6gg1jgXVrFru8zHSfY
6+
Gr9tniFSkdnrP/XHaEkQwEPptUlRF1eG+3hOO1D1vW0SliXBfg1DWd/Yew55kljzmtgxsg
7+
J2dfTYZF5L6xblNjM6mr5NItdhUsVB4XsYWo4=
8+
-----END OPENSSH PRIVATE KEY-----
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
-----BEGIN OPENSSH PRIVATE KEY-----
2+
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
3+
QyNTUxOQAAACCCsGI6AEHghOMbGIhtsRX59CjoqwkCgDMLgOqGByvrPAAAAKDryTjh68k4
4+
4QAAAAtzc2gtZWQyNTUxOQAAACCCsGI6AEHghOMbGIhtsRX59CjoqwkCgDMLgOqGByvrPA
5+
AAAECcZJX7mXgmBR60wXj51bhpkw21jDt95z4VBbXHEjbgMYKwYjoAQeCE4xsYiG2xFfn0
6+
KOirCQKAMwuA6oYHK+s8AAAAFnNyaW5rZXNAV0lOREVWLVNSSU5LRVMBAgMEBQYH
7+
-----END OPENSSH PRIVATE KEY-----

src/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,12 @@
717717
<EmbeddedResource Include="Data\Key.ECDSA384.Encrypted.txt" />
718718
<EmbeddedResource Include="Data\Key.ECDSA521.Encrypted.txt" />
719719
</ItemGroup>
720+
<ItemGroup>
721+
<EmbeddedResource Include="Data\Key.ED25519.txt" />
722+
</ItemGroup>
723+
<ItemGroup>
724+
<EmbeddedResource Include="Data\Key.ED25519.Encrypted.txt" />
725+
</ItemGroup>
720726
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
721727
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
722728
Other similar extension points exist, see Microsoft.Common.targets.

src/Renci.SshNet/ConnectionInfo.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ public ConnectionInfo(string host, int port, string username, ProxyTypes proxyTy
384384
{"ecdsa-sha2-nistp384", data => new KeyHostAlgorithm("ecdsa-sha2-nistp384", new EcdsaKey(), data)},
385385
{"ecdsa-sha2-nistp521", data => new KeyHostAlgorithm("ecdsa-sha2-nistp521", new EcdsaKey(), data)},
386386
#endif
387+
{"ssh-ed25519", data => new KeyHostAlgorithm("ssh-ed25519", new ED25519Key(), data)},
387388
//{"x509v3-sign-rsa", () => { ... },
388389
//{"x509v3-sign-dss", () => { ... },
389390
//{"spki-sign-rsa", () => { ... },

src/Renci.SshNet/OpenSSHKeyReader.cs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
using Renci.SshNet.Common;
2+
using Renci.SshNet.Security;
3+
using System.Text;
4+
5+
namespace Renci.SshNet
6+
{
7+
class OpenSSHKeyReader : SshData
8+
{
9+
// See doc: https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key
10+
// Reference: https://github.com/net-ssh/net-ssh/blob/dd13dd44d68b7fa82d4ca9a3bbe18e30c855f1d2/lib/net/ssh/authentication/ed25519.rb
11+
12+
const string AUTH_MAGIC = "openssh-key-v1";
13+
14+
public OpenSSHKeyReader(byte[] data)
15+
{
16+
Load(data);
17+
}
18+
19+
public ED25519Key ReadKey()
20+
{
21+
var magic = Encoding.ASCII.GetString(ReadBytes(AUTH_MAGIC.Length));
22+
if (magic != AUTH_MAGIC)
23+
throw new SshException("Unsupported OPENSSH Format: " + magic);
24+
25+
ReadByte(); // 0 terminated String
26+
27+
var cipher = ReadString(Encoding.ASCII);
28+
var kdfname = ReadString(Encoding.ASCII);
29+
var kdfoptions = ReadString(Encoding.ASCII);
30+
31+
var num_keys = ReadUInt32();
32+
33+
if (num_keys > 1)
34+
throw new SshException("Currently just one key is supported");
35+
36+
// we don't care for the Public-Keys
37+
for (int i = 0; i < num_keys; i++)
38+
{
39+
ReadString(Encoding.ASCII);
40+
}
41+
42+
var len = ReadUInt32();
43+
44+
// XXX decrypt Data
45+
46+
var checkint1 = ReadUInt32();
47+
var checkint2 = ReadUInt32();
48+
49+
if (checkint1 != checkint2)
50+
throw new SshException(string.Format("Check Integer mismatch: {0} <-> {1}", checkint1, checkint2));
51+
52+
var keytype = ReadString(Encoding.ASCII);
53+
if (keytype != "ssh-ed25519")
54+
throw new SshException("Unsupported Key-Type: " + keytype);
55+
len = ReadUInt32();
56+
var pk = ReadBytes((int)len).Reverse();
57+
len = ReadUInt32();
58+
var sk = ReadBytes((int)len);
59+
var comment = ReadString(Encoding.ASCII);
60+
61+
return new ED25519Key(pk, sk);
62+
}
63+
64+
protected override void LoadData()
65+
{
66+
}
67+
68+
protected override void SaveData()
69+
{
70+
}
71+
}
72+
}

src/Renci.SshNet/PrivateKeyFile.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,11 @@ private void Open(Stream privateKey, string passPhrase)
203203
HostKey = new KeyHostAlgorithm(_key.ToString(), _key);
204204
break;
205205
#endif
206+
case "OPENSSH":
207+
var ssh_reader = new OpenSSHKeyReader(decryptedData);
208+
_key = ssh_reader.ReadKey();
209+
HostKey = new KeyHostAlgorithm(_key.ToString(), _key);
210+
break;
206211
case "SSH2 ENCRYPTED":
207212
var reader = new SshDataReader(decryptedData);
208213
var magicNumber = reader.ReadUInt32();

src/Renci.SshNet/Renci.SshNet.csproj

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,12 +164,78 @@
164164
<Compile Include="Messages\Transport\KeyExchangeEcdhInitMessage.cs" />
165165
<Compile Include="Messages\Transport\KeyExchangeEcdhReplyMessage.cs" />
166166
<Compile Include="Netconf\INetConfSession.cs" />
167+
<Compile Include="OpenSSHKeyReader.cs" />
167168
<Compile Include="RemotePathDoubleQuoteTransformation.cs" />
168169
<Compile Include="RemotePathNoneTransformation.cs" />
169170
<Compile Include="RemotePathShellQuoteTransformation.cs" />
170171
<Compile Include="RemotePathTransformation.cs" />
172+
<Compile Include="Security\Cryptography\Ciphers\Ed255129.cs" />
173+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Array16.cs" />
174+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Array8.cs" />
175+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\ByteIntegerConverter.cs" />
176+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\CryptoBytes.cs" />
177+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519.cs" />
178+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\base.cs" />
179+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\base2.cs" />
180+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\d.cs" />
181+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\d2.cs" />
182+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\fe_0.cs" />
183+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\fe_1.cs" />
184+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\fe_add.cs" />
185+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\fe_cmov.cs" />
186+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\fe_cswap.cs" />
187+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\fe_frombytes.cs" />
188+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\fe_invert.cs" />
189+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\fe_isnegative.cs" />
190+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\fe_isnonzero.cs" />
191+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\fe_mul.cs" />
192+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\fe_mul121666.cs" />
193+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\fe_neg.cs" />
194+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\fe_pow22523.cs" />
195+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\fe_sq.cs" />
196+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\fe_sq2.cs" />
197+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\fe_sub.cs" />
198+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\fe_tobytes.cs" />
199+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\FieldElement.cs" />
200+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\ge_add.cs" />
201+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\ge_double_scalarmult.cs" />
202+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\ge_frombytes.cs" />
203+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\ge_madd.cs" />
204+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\ge_msub.cs" />
205+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\ge_p1p1_to_p2.cs" />
206+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\ge_p1p1_to_p3.cs" />
207+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\ge_p2_0.cs" />
208+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\ge_p2_dbl.cs" />
209+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\ge_p3_0.cs" />
210+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\ge_p3_dbl.cs" />
211+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\ge_p3_tobytes.cs" />
212+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\ge_p3_to_cached.cs" />
213+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\ge_p3_to_p2.cs" />
214+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\ge_precomp_0.cs" />
215+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\ge_scalarmult_base.cs" />
216+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\ge_sub.cs" />
217+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\ge_tobytes.cs" />
218+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\GroupElement.cs" />
219+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\keypair.cs" />
220+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\open.cs" />
221+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\scalarmult.cs" />
222+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\sc_clamp.cs" />
223+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\sc_mul_add.cs" />
224+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\sc_reduce.cs" />
225+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\sign.cs" />
226+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Ed25519Ref10\sqrtm1.cs" />
227+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\InternalAssert.cs" />
228+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\MontgomeryCurve25519.cs" />
229+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Poly1305Donna.cs" />
230+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Salsa\Salsa20.cs" />
231+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Salsa\SalsaCore.cs" />
232+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Sha512.cs" />
233+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\Sha512Internal.cs" />
234+
<Compile Include="Security\Cryptography\Ciphers\Ed255129\XSalsa20Poly1305.cs" />
235+
<Compile Include="Security\Cryptography\ED25519DigitalSignature.cs" />
171236
<Compile Include="Security\Cryptography\EcdsaDigitalSignature.cs" />
172237
<Compile Include="Security\Cryptography\EcdsaKey.cs" />
238+
<Compile Include="Security\Cryptography\ED25519Key.cs" />
173239
<Compile Include="Security\Cryptography\HMACMD5.cs" />
174240
<Compile Include="Security\Cryptography\HMACSHA1.cs" />
175241
<Compile Include="Security\Cryptography\HMACSHA256.cs" />
@@ -467,10 +533,14 @@
467533
<Link>Renci.SshNet.snk</Link>
468534
</None>
469535
<None Include="Documentation\Renci.SshNet.content" />
536+
<None Include="Security\Cryptography\Ciphers\Ed255129\readme.md" />
470537
</ItemGroup>
471538
<ItemGroup>
472539
<Content Include="Documentation\SshNet.shfbproj" />
540+
<Content Include="Security\Cryptography\Ciphers\Ed255129\License.txt" />
541+
<Content Include="Security\Cryptography\Ciphers\Ed255129\Salsa\replace regex.txt" />
473542
</ItemGroup>
543+
<ItemGroup />
474544
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
475545
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
476546
Other similar extension points exist, see Microsoft.Common.targets.
@@ -479,4 +549,4 @@
479549
<Target Name="AfterBuild">
480550
</Target>
481551
-->
482-
</Project>
552+
</Project>

0 commit comments

Comments
 (0)