Skip to content

Commit

Permalink
Update keygen
Browse files Browse the repository at this point in the history
  • Loading branch information
styris-ame committed Nov 26, 2024
1 parent 4302dd9 commit 8e97510
Show file tree
Hide file tree
Showing 87 changed files with 9,857 additions and 12 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ obj
bin
!Packaging/DPKG/usr/bin
ppa-private-key.asc
*.DotSettings.user
6 changes: 6 additions & 0 deletions src/Jumper.sln
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PostInstallScript", "PostIn
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PostRemoveScript", "PostRemoveScript\PostRemoveScript.csproj", "{4071FA63-3C60-49C9-BE4D-487C8C1041F1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SshNet.Keygen", "SshNet.Keygen\SshNet.Keygen.csproj", "{6A2CC913-DE7D-40E2-AB18-BAC59CE16181}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Expand All @@ -24,5 +26,9 @@ Global
{4071FA63-3C60-49C9-BE4D-487C8C1041F1}.Debug|x64.Build.0 = Debug|Any CPU
{4071FA63-3C60-49C9-BE4D-487C8C1041F1}.Release|x64.ActiveCfg = Release|Any CPU
{4071FA63-3C60-49C9-BE4D-487C8C1041F1}.Release|x64.Build.0 = Release|Any CPU
{6A2CC913-DE7D-40E2-AB18-BAC59CE16181}.Debug|x64.ActiveCfg = Debug|Any CPU
{6A2CC913-DE7D-40E2-AB18-BAC59CE16181}.Debug|x64.Build.0 = Debug|Any CPU
{6A2CC913-DE7D-40E2-AB18-BAC59CE16181}.Release|x64.ActiveCfg = Release|Any CPU
{6A2CC913-DE7D-40E2-AB18-BAC59CE16181}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
11 changes: 0 additions & 11 deletions src/Jumper.sln.DotSettings.user

This file was deleted.

5 changes: 4 additions & 1 deletion src/Jumper/Jumper.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
<PackageReference Include="CommandLineParser" Version="2.9.1" />
<PackageReference Include="Konscious.Security.Cryptography.Argon2" Version="1.3.1" />
<PackageReference Include="SSH.NET" Version="2024.2.0" />
<PackageReference Include="SshNet.Keygen" Version="2024.0.0.2" />
<PackageReference Include="Vecc.YamlDotNet.Analyzers.StaticGenerator" Version="16.2.0" />
<PackageReference Include="YamlDotNet" Version="16.2.0" />
</ItemGroup>
Expand All @@ -56,4 +55,8 @@
<None Remove="PostRemoveScript\**" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\SshNet.Keygen\SshNet.Keygen.csproj" />
</ItemGroup>

</Project>
190 changes: 190 additions & 0 deletions src/SshNet.Keygen/Chaos.NaCl/CryptoBytes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
using System;
using System.Runtime.CompilerServices;

namespace Chaos.NaCl
{
public static class CryptoBytes
{
public static bool ConstantTimeEquals(byte[] x, byte[] y)
{
if (x == null)
throw new ArgumentNullException("x");
if (y == null)
throw new ArgumentNullException("y");
if (x.Length != y.Length)
throw new ArgumentException("x.Length must equal y.Length");
return InternalConstantTimeEquals(x, 0, y, 0, x.Length) != 0;
}

public static bool ConstantTimeEquals(ArraySegment<byte> x, ArraySegment<byte> y)
{
if (x.Array == null)
throw new ArgumentNullException("x.Array");
if (y.Array == null)
throw new ArgumentNullException("y.Array");
if (x.Count != y.Count)
throw new ArgumentException("x.Count must equal y.Count");

return InternalConstantTimeEquals(x.Array, x.Offset, y.Array, y.Offset, x.Count) != 0;
}

public static bool ConstantTimeEquals(byte[] x, int xOffset, byte[] y, int yOffset, int length)
{
if (x == null)
throw new ArgumentNullException("x");
if (xOffset < 0)
throw new ArgumentOutOfRangeException("xOffset", "xOffset < 0");
if (y == null)
throw new ArgumentNullException("y");
if (yOffset < 0)
throw new ArgumentOutOfRangeException("yOffset", "yOffset < 0");
if (length < 0)
throw new ArgumentOutOfRangeException("length", "length < 0");
if (x.Length - xOffset < length)
throw new ArgumentException("xOffset + length > x.Length");
if (y.Length - yOffset < length)
throw new ArgumentException("yOffset + length > y.Length");

return InternalConstantTimeEquals(x, xOffset, y, yOffset, length) != 0;
}

private static uint InternalConstantTimeEquals(byte[] x, int xOffset, byte[] y, int yOffset, int length)
{
int differentbits = 0;
for (int i = 0; i < length; i++)
differentbits |= x[xOffset + i] ^ y[yOffset + i];
return (1 & (unchecked((uint)differentbits - 1) >> 8));
}

public static void Wipe(byte[] data)
{
if (data == null)
throw new ArgumentNullException("data");
InternalWipe(data, 0, data.Length);
}

public static void Wipe(byte[] data, int offset, int count)
{
if (data == null)
throw new ArgumentNullException("data");
if (offset < 0)
throw new ArgumentOutOfRangeException("offset");
if (count < 0)
throw new ArgumentOutOfRangeException("count", "Requires count >= 0");
if ((uint)offset + (uint)count > (uint)data.Length)
throw new ArgumentException("Requires offset + count <= data.Length");
InternalWipe(data, offset, count);
}

public static void Wipe(ArraySegment<byte> data)
{
if (data.Array == null)
throw new ArgumentNullException("data.Array");
InternalWipe(data.Array, data.Offset, data.Count);
}

// Secure wiping is hard
// * the GC can move around and copy memory
// Perhaps this can be avoided by using unmanaged memory or by fixing the position of the array in memory
// * Swap files and error dumps can contain secret information
// It seems possible to lock memory in RAM, no idea about error dumps
// * Compiler could optimize out the wiping if it knows that data won't be read back
// I hope this is enough, suppressing inlining
// but perhaps `RtlSecureZeroMemory` is needed
[MethodImpl(MethodImplOptions.NoInlining)]
internal static void InternalWipe(byte[] data, int offset, int count)
{
Array.Clear(data, offset, count);
}

// shallow wipe of structs
[MethodImpl(MethodImplOptions.NoInlining)]
internal static void InternalWipe<T>(ref T data)
where T : struct
{
data = default(T);
}

// constant time hex conversion
// see http://stackoverflow.com/a/14333437/445517
//
// An explanation of the weird bit fiddling:
//
// 1. `bytes[i] >> 4` extracts the high nibble of a byte
// `bytes[i] & 0xF` extracts the low nibble of a byte
// 2. `b - 10`
// is `< 0` for values `b < 10`, which will become a decimal digit
// is `>= 0` for values `b > 10`, which will become a letter from `A` to `F`.
// 3. Using `i >> 31` on a signed 32 bit integer extracts the sign, thanks to sign extension.
// It will be `-1` for `i < 0` and `0` for `i >= 0`.
// 4. Combining 2) and 3), shows that `(b-10)>>31` will be `0` for letters and `-1` for digits.
// 5. Looking at the case for letters, the last summand becomes `0`, and `b` is in the range 10 to 15. We want to map it to `A`(65) to `F`(70), which implies adding 55 (`'A'-10`).
// 6. Looking at the case for digits, we want to adapt the last summand so it maps `b` from the range 0 to 9 to the range `0`(48) to `9`(57). This means it needs to become -7 (`'0' - 55`).
// Now we could just multiply with 7. But since -1 is represented by all bits being 1, we can instead use `& -7` since `(0 & -7) == 0` and `(-1 & -7) == -7`.
//
// Some further considerations:
//
// * I didn't use a second loop variable to index into `c`, since measurement shows that calculating it from `i` is cheaper.
// * Using exactly `i < bytes.Length` as upper bound of the loop allows the JITter to eliminate bounds checks on `bytes[i]`, so I chose that variant.
// * Making `b` an int avoids unnecessary conversions from and to byte.
public static string ToHexStringUpper(byte[] data)
{
if (data == null)
return null;
char[] c = new char[data.Length * 2];
int b;
for (int i = 0; i < data.Length; i++)
{
b = data[i] >> 4;
c[i * 2] = (char)(55 + b + (((b - 10) >> 31) & -7));
b = data[i] & 0xF;
c[i * 2 + 1] = (char)(55 + b + (((b - 10) >> 31) & -7));
}
return new string(c);
}

// Explanation is similar to ToHexStringUpper
// constant 55 -> 87 and -7 -> -39 to compensate for the offset 32 between lowercase and uppercase letters
public static string ToHexStringLower(byte[] data)
{
if (data == null)
return null;
char[] c = new char[data.Length * 2];
int b;
for (int i = 0; i < data.Length; i++)
{
b = data[i] >> 4;
c[i * 2] = (char)(87 + b + (((b - 10) >> 31) & -39));
b = data[i] & 0xF;
c[i * 2 + 1] = (char)(87 + b + (((b - 10) >> 31) & -39));
}
return new string(c);
}

public static byte[] FromHexString(string hexString)
{
if (hexString == null)
return null;
if (hexString.Length % 2 != 0)
throw new FormatException("The hex string is invalid because it has an odd length");
var result = new byte[hexString.Length / 2];
for (int i = 0; i < result.Length; i++)
result[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
return result;
}

public static string ToBase64String(byte[] data)
{
if (data == null)
return null;
return Convert.ToBase64String(data);
}

public static byte[] FromBase64String(string s)
{
if (s == null)
return null;
return Convert.FromBase64String(s);
}
}
}
Loading

0 comments on commit 8e97510

Please sign in to comment.