-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
294 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
bla |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
-----BEGIN SSH SIGNATURE----- | ||
U1NIU0lHAAAAAQAAARcAAAAHc3NoLXJzYQAAAAMBAAEAAAEBAOJpdVVMNyPkABr2ywB2iO | ||
ns3StUJMUNDGuFjqyNzVYvaX3C8rjB6i1EoBCHbp6ZPEEU8e6bOPU6i2hvQTjFWxqmaRvj | ||
3hz7VAu+wMMmQkw1IMZyw2YhKi/+sCz8Yb3vI2xUHR1PZLtZj7K47prVLkbiWtycIiJaCD | ||
n9nI1QYeHX40in+0witV9D6T+tieUbyda/3C31KL1y5Vs4plHssEWayKq/Yi5xqWLAitGO | ||
KGUofEk1N0FEagJrMEzfDiEUxbFOFjedRo2lfgY/KUUzc1gabNYHH927P+gup/60pYLM9s | ||
MpgjBB8v1KJ2F/tCBKMyX0BZ7QYhWvVMFIM4F3SycAAAAEZmlsZQAAAAAAAAAGc2hhNTEy | ||
AAABFAAAAAxyc2Etc2hhMi01MTIAAAEA2WMT5aZ6fJ/ZXF0Gl/Vym8mTtDXEufziwjmt+z | ||
ZSt3MF0GlwNDiYkeHFjyg16zqrJkeddj7yENyQ0Eae0Ew+7iFML6sKTEJKaiYf51/U+Jli | ||
DVawwhH0+i3YZaCGmbiEQeXHfuFtA8deCdyxUkUYbycpdrfd0bx2dZFYu/WgNa9gHu/OVO | ||
NQqqDOAHZUAko2MHN2GZ7wiepbGO9NAjhRtRE2tV6X8l3KI1+PmqvyfOQQMZcVa1V/WaFR | ||
8wx1Z3VBJ+szP0XBdWrrwKY8K7yEE5rm55mx2rGtXuySGgISMbZlUHlJp31YE0Z4jMcEE+ | ||
5m61gVpll8DYFSakNlBk6Xgg== | ||
-----END SSH SIGNATURE----- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
using System.Security.Cryptography; | ||
using Renci.SshNet.Security; | ||
|
||
namespace SshNet.Keygen.Extensions | ||
{ | ||
public static class KeyHostAlgorithmExtension | ||
{ | ||
#region Sign | ||
|
||
internal static string Sign(this KeyHostAlgorithm keyHostAlgorithm, byte[] data, HashAlgorithmName hashAlgorithmName) | ||
{ | ||
return SshSignature.Sign(keyHostAlgorithm, data, hashAlgorithmName); | ||
} | ||
|
||
internal static void SignFile(this KeyHostAlgorithm keyHostAlgorithm, string path, HashAlgorithmName hashAlgorithmName) | ||
{ | ||
SshSignature.SignFile(keyHostAlgorithm, path, hashAlgorithmName); | ||
} | ||
|
||
#endregion | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
using System; | ||
using System.Data; | ||
using System.IO; | ||
using System.Security.Cryptography; | ||
using System.Text; | ||
using System.Text.RegularExpressions; | ||
using Renci.SshNet.Common; | ||
using Renci.SshNet.Security; | ||
using Renci.SshNet.Security.Cryptography; | ||
using SshNet.Keygen.Extensions; | ||
|
||
namespace SshNet.Keygen | ||
{ | ||
public class SshSignature | ||
{ | ||
private static readonly Regex SshSignatureRegex = new( | ||
"^-+ *BEGIN SSH SIGNATURE *-+(\\r|\\n)*(?<data>([a-zA-Z0-9/+=]{1,80}(\\r|\\n)+)+)(\\r|\\n)*-+ *END SSH SIGNATURE *-+", | ||
RegexOptions.Compiled | RegexOptions.Multiline); | ||
|
||
private static readonly string Preambel = "SSHSIG"; | ||
private static readonly uint Version = 1; | ||
|
||
public static bool VerifyFile(string path, string signaturePath) | ||
{ | ||
return Verify(File.ReadAllBytes(path), File.ReadAllText(signaturePath)); | ||
} | ||
|
||
public static bool Verify(byte[] data, string signature) | ||
{ | ||
var signatureMatch = SshSignatureRegex.Match(signature); | ||
if (!signatureMatch.Success) | ||
{ | ||
throw new SshException("Invalid SSH signature"); | ||
} | ||
|
||
var signatureData = signatureMatch.Result("${data}"); | ||
var binaryData = Convert.FromBase64String(signatureData); | ||
|
||
var stream = new MemoryStream(binaryData); | ||
var reader = new SshSignatureReader(stream); | ||
|
||
if (Encoding.ASCII.GetString(reader.ReadBytes(6)) != Preambel) | ||
throw new SshException("Wrong preamble"); | ||
|
||
if (reader.ReadUInt32() != Version) | ||
throw new SshException("Wrong version"); | ||
|
||
var pubKeyLength = reader.ReadUInt32(); // pub key length | ||
var pubKeyData = reader.ReadBytes((int)pubKeyLength); // pubkey | ||
|
||
var @namespace = reader.ReadString(); // namespace | ||
reader.ReadString(); // reserved | ||
var hashAlgo = reader.ReadString(); // hash-algo | ||
var hashAlgorithm = HashAlgorithm.Create(hashAlgo); | ||
|
||
if (hashAlgorithm is null) | ||
throw new SshException($"Unknown hash algorithm {hashAlgo}"); | ||
|
||
var encodedSignatureLength = reader.ReadUInt32(); | ||
var encodedSignature = reader.ReadBytes((int)encodedSignatureLength); | ||
var signatureStream = new MemoryStream(encodedSignature); | ||
var signatureReader = new SshSignatureReader(signatureStream); | ||
|
||
var sigAlgo = signatureReader.ReadString(); // sig algo | ||
var sigLength = signatureReader.ReadUInt32(); // sig length | ||
var sigData = signatureReader.ReadBytes((int)sigLength); // sig | ||
|
||
DigitalSignature digitalSignature; | ||
Key key; | ||
|
||
switch (sigAlgo) | ||
{ | ||
case "rsa-sha2-512": | ||
key = new RsaKey(new SshKeyData(pubKeyData)); | ||
digitalSignature = new RsaDigitalSignature((RsaKey)key, HashAlgorithmName.SHA512); | ||
break; | ||
case "rsa-sha2-256": | ||
key = new RsaKey(new SshKeyData(pubKeyData)); | ||
digitalSignature = new RsaDigitalSignature((RsaKey)key, HashAlgorithmName.SHA256); | ||
break; | ||
case "ssh-ed25519": | ||
key = new ED25519Key(new SshKeyData(pubKeyData)); | ||
digitalSignature = new ED25519DigitalSignature((ED25519Key)key); | ||
break; | ||
case "ecdsa-sha2-nistp256": | ||
case "ecdsa-sha2-nistp384": | ||
case "ecdsa-sha2-nistp521": | ||
key = new EcdsaKey(new SshKeyData(pubKeyData)); | ||
digitalSignature = new EcdsaDigitalSignature((EcdsaKey)key); | ||
break; | ||
default: | ||
throw new SshException($"Unknown signature algorithm {sigAlgo}"); | ||
} | ||
|
||
var verifyStream = new MemoryStream(); | ||
var verifyWriter = new BinaryWriter(verifyStream); | ||
verifyWriter.Write(Encoding.ASCII.GetBytes(Preambel)); | ||
verifyWriter.EncodeBinary(@namespace); | ||
verifyWriter.EncodeBinary(""); // reserved | ||
verifyWriter.EncodeBinary(hashAlgo); | ||
verifyWriter.EncodeBinary(hashAlgorithm.ComputeHash(data)); | ||
|
||
return digitalSignature.Verify(verifyStream.ToArray(), sigData); | ||
} | ||
|
||
public static void SignFile(KeyHostAlgorithm keyHostAlgorithm, string path, HashAlgorithmName hashAlgorithmName) | ||
{ | ||
var sigFile = $"{path}.sig"; | ||
File.WriteAllText(sigFile, Sign(keyHostAlgorithm, File.ReadAllBytes(path), hashAlgorithmName)); | ||
} | ||
|
||
public static string Sign(KeyHostAlgorithm keyHostAlgorithm, byte[] data, HashAlgorithmName hashAlgorithmName) | ||
{ | ||
var @namespace = "file"; // ToDo: expose? | ||
|
||
using var pubStream = new MemoryStream(); | ||
using var pubWriter = new BinaryWriter(pubStream); | ||
keyHostAlgorithm.Key.PublicKeyData(pubWriter); | ||
|
||
var hashAlgorithm = HashAlgorithm.Create(hashAlgorithmName.Name); | ||
if (hashAlgorithm is null) | ||
throw new SshException($"Unknown hash algorithm {hashAlgorithmName.Name}"); | ||
|
||
var signStream = new MemoryStream(); | ||
var signWriter = new BinaryWriter(signStream); | ||
signWriter.Write(Encoding.ASCII.GetBytes(Preambel)); | ||
signWriter.EncodeBinary(@namespace); | ||
signWriter.EncodeBinary(""); // reserved | ||
signWriter.EncodeBinary(hashAlgorithmName.Name.ToLower()); | ||
signWriter.EncodeBinary(hashAlgorithm.ComputeHash(data)); | ||
var signed = keyHostAlgorithm.DigitalSignature.Sign(signStream.ToArray()); | ||
|
||
var signatureStream = new MemoryStream(); | ||
var signatureWriter = new BinaryWriter(signatureStream); | ||
signatureWriter.EncodeBinary(keyHostAlgorithm.Name); | ||
signatureWriter.EncodeBinary(signed); | ||
|
||
var stream = new MemoryStream(); | ||
var writer = new BinaryWriter(stream); | ||
|
||
writer.Write(Encoding.ASCII.GetBytes(Preambel)); | ||
writer.EncodeUInt(Version); | ||
writer.EncodeBinary(pubStream.ToArray()); | ||
writer.EncodeBinary(@namespace); | ||
writer.EncodeBinary(""); // reserved | ||
writer.EncodeBinary(hashAlgorithmName.Name.ToLower()); | ||
writer.EncodeBinary(signatureStream.ToArray()); | ||
|
||
var base64 = Convert.ToBase64String(stream.ToArray()).ToCharArray(); | ||
var pem = new StringWriter(); | ||
for (var i = 0; i < base64.Length; i += 70) | ||
{ | ||
pem.Write(base64, i, Math.Min(70, base64.Length - i)); | ||
pem.Write(Environment.NewLine); | ||
} | ||
|
||
var s = new StringWriter(); | ||
s.Write($"-----BEGIN SSH SIGNATURE-----{Environment.NewLine}"); | ||
s.Write(pem.ToString()); | ||
s.Write("-----END SSH SIGNATURE-----"); | ||
return s.ToString(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
using System; | ||
using System.IO; | ||
using System.Text; | ||
|
||
namespace SshNet.Keygen | ||
{ | ||
public class SshSignatureReader : BinaryReader | ||
{ | ||
public SshSignatureReader(Stream input) : base(input, Encoding.Default, true) | ||
{ | ||
} | ||
|
||
public override uint ReadUInt32() | ||
{ | ||
var data = base.ReadBytes(4); | ||
if (BitConverter.IsLittleEndian) | ||
Array.Reverse(data); | ||
return BitConverter.ToUInt32(data, 0); | ||
} | ||
|
||
public byte[] ReadStringAsBytes() | ||
{ | ||
var len = (int)ReadUInt32(); | ||
return base.ReadBytes(len); | ||
} | ||
|
||
public override string ReadString() | ||
{ | ||
return Encoding.ASCII.GetString(ReadStringAsBytes()); | ||
} | ||
} | ||
} |