Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Security and Privacy #59

Merged
merged 8 commits into from
May 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
767 changes: 767 additions & 0 deletions NOnion.Tests/Directory-Samples/KeyCertificate.json

Large diffs are not rendered by default.

662 changes: 662 additions & 0 deletions NOnion.Tests/Directory-Samples/KeyCertificate.txt

Large diffs are not rendered by default.

488,541 changes: 488,540 additions & 1 deletion NOnion.Tests/Directory-Samples/NetworkStatus.json

Large diffs are not rendered by default.

16 changes: 15 additions & 1 deletion NOnion.Tests/DirectoryParsers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public void CanParseNetworkStatusDocumentAndConvertToJson ()
var expectedNetworkStatusJson = File.ReadAllText($"Directory-Samples{Path.DirectorySeparatorChar}NetworkStatus.json");

NetworkStatusDocument networkStatus = NetworkStatusDocument.Parse(networkStatusStr);
var networkStatusJson = JsonConvert.SerializeObject(networkStatus);
var networkStatusJson = JsonConvert.SerializeObject(networkStatus, Formatting.Indented);

Assert.That(networkStatusJson, Is.EqualTo(expectedNetworkStatusJson));
}
Expand Down Expand Up @@ -49,5 +49,19 @@ public void CanParseMicroDescriptorAndConvertToJson()

Assert.That(microDescriptorJson, Is.EqualTo(expectedMicroDescriptorsJson));
}

[Test]
public void CanParseKeyCertificateAndConvertToJson()
{
// Tor directory spec enforces documents to use \n (The ascii LF character (hex value 0x0a))
var keyCertificatesStr = File.ReadAllText($"Directory-Samples{Path.DirectorySeparatorChar}KeyCertificate.txt").Replace("\r\n", "\n");
var expectedKeyCertificatesJson = File.ReadAllText($"Directory-Samples{Path.DirectorySeparatorChar}KeyCertificate.json");

var keyCertificates = KeyCertificateEntry.ParseMany(keyCertificatesStr);
var keyCertificatesJson = JsonConvert.SerializeObject(keyCertificates, Formatting.Indented);

Assert.That(keyCertificatesJson, Is.EqualTo(expectedKeyCertificatesJson));
}

}
}
6 changes: 6 additions & 0 deletions NOnion.Tests/NOnion.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@
</ItemGroup>

<ItemGroup>
<Content Include="Directory-Samples\KeyCertificate.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Directory-Samples\KeyCertificate.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Directory-Samples\MicroDescriptor.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
Expand Down
17 changes: 15 additions & 2 deletions NOnion.Tests/TorDirectoryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,22 @@ public class TorDirectoryTests
[SetUp]
public void Init()
{
cachePath =
new DirectoryInfo(
Path.Combine(
Path.GetTempPath(),
Path.GetFileNameWithoutExtension(
Path.GetRandomFileName()
)
)
);
cachePath.Create();

TorLogger.Init(TestContext.Progress.WriteLine);
}

private DirectoryInfo cachePath = null;

/* It's possible that the router returned by GetRandomFallbackDirectory be inaccessable
* so we need to continue retrying if an exceptions happened to make sure the issues are
* not related to the router we randomly chose
Expand All @@ -28,7 +41,7 @@ public void Init()

private async Task BootstrapTorDirectory()
{
await TorDirectory.BootstrapAsync(FallbackDirectorySelector.GetRandomFallbackDirectory(), new DirectoryInfo(Path.GetTempPath()));
await TorDirectory.BootstrapAsync(FallbackDirectorySelector.GetRandomFallbackDirectory(), cachePath);
}

[Test]
Expand All @@ -40,7 +53,7 @@ public void CanBootstrapTorDirectory()

private async Task ReturnRandomRouter()
{
TorDirectory directory = await TorDirectory.BootstrapAsync(FallbackDirectorySelector.GetRandomFallbackDirectory(), new DirectoryInfo(Path.GetTempPath()));
TorDirectory directory = await TorDirectory.BootstrapAsync(FallbackDirectorySelector.GetRandomFallbackDirectory(), cachePath);
var (endPoint, router) = await directory.GetRouterAsync(RouterType.Normal);
Assert.IsTrue(router.IsCreate);
Assert.IsFalse(((CircuitNodeDetail.Create)router).IdentityKey.All(x => x == 0));
Expand Down
4 changes: 4 additions & 0 deletions NOnion/Constants.fs
Original file line number Diff line number Diff line change
Expand Up @@ -197,3 +197,7 @@ module Constants =

let internal CertificateCertifiedKeyLength = 32
let internal CertificateSignatureLength = 64

module CertTypes =
let Link = 1uy
let ID = 2uy
knocte marked this conversation as resolved.
Show resolved Hide resolved
20 changes: 20 additions & 0 deletions NOnion/Crypto/DirectoryCipher.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace NOnion.Crypto

open System.Security.Cryptography

open Org.BouncyCastle.Crypto.Parameters
open Org.BouncyCastle.Security

module DirectoryCipher =
let SHA1(bytes: array<byte>) =
let sha1Engine = SHA1.Create()
sha1Engine.ComputeHash bytes

let SHA256(bytes: array<byte>) =
let sha256Engine = SHA256.Create()
sha256Engine.ComputeHash bytes

let DecryptSignature (publicKey: RsaKeyParameters) (data: array<byte>) =
let cipher = CipherUtilities.GetCipher "RSA/None/PKCS1Padding"
cipher.Init(false, publicKey)
cipher.DoFinal data
15 changes: 5 additions & 10 deletions NOnion/Directory/HiddenServiceDescriptorDocument.fs
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ type IntroductionPointEntry =
let words = lines.Peek().Split ' ' |> MutableQueue<string>

let rec readBlock(state: string) =
let line = lines.Dequeue()
let line = sprintf "%s\n" (lines.Dequeue())

if line.StartsWith "-----END" then
state
state + line
else
readBlock(state + line)

Expand Down Expand Up @@ -73,28 +73,23 @@ type IntroductionPointEntry =
}
| "auth-key" ->
lines.Dequeue() |> ignore<string>
//get rid of begin
lines.Dequeue() |> ignore<string>

innerParse
{ state with
AuthKey =
readBlock String.Empty
|> Convert.FromBase64String
|> PemUtility.PemToByteArray
|> Certificate.FromBytes
|> Some
}
| "enc-key-cert" ->
lines.Dequeue() |> ignore<string>
//get rid of begin
lines.Dequeue() |> ignore<string>


innerParse
{ state with
EncKeyCert =
readBlock String.Empty
|> Convert.FromBase64String
|> PemUtility.PemToByteArray
|> Certificate.FromBytes
|> Some
}
Expand Down Expand Up @@ -211,7 +206,7 @@ type HiddenServiceDescriptorDocument =
let lines = stringToParse.Split '\n' |> MutableQueue<string>

let rec readBlock(state: string) =
let line = lines.Dequeue()
let line = sprintf "%s\n" (lines.Dequeue())

if line.StartsWith "-----END" then
state + line
Expand Down
25 changes: 5 additions & 20 deletions NOnion/Directory/HiddenServiceFirstLayerDescriptorDocument.fs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ type HiddenServiceFirstLayerDescriptorDocument =
let lines = stringToParse.Split '\n' |> MutableQueue<string>

let rec readBlock(state: string) =
let line = lines.Dequeue()
let line = sprintf "%s\n" (lines.Dequeue())

if line.StartsWith "-----END" then
state + line
Expand Down Expand Up @@ -153,16 +153,8 @@ type HiddenServiceFirstLayerDescriptorDocument =

{ state with
HiddenServiceFirstLayerDescriptorDocument.SigningKeyCert =
(readBlock String.Empty)
.Replace(
"-----BEGIN ED25519 CERT-----",
String.Empty
)
.Replace(
"-----END ED25519 CERT-----",
String.Empty
)
|> Convert.FromBase64String
readBlock String.Empty
|> PemUtility.PemToByteArray
|> Certificate.FromBytes
|> Some
}
Expand All @@ -176,17 +168,10 @@ type HiddenServiceFirstLayerDescriptorDocument =
| "superencrypted" ->
lines.Dequeue() |> ignore<string>

let payloadString = readBlock String.Empty

{ state with
HiddenServiceFirstLayerDescriptorDocument.EncryptedPayload =
payloadString
.Replace(
"-----BEGIN MESSAGE-----",
String.Empty
)
.Replace("-----END MESSAGE-----", String.Empty)
|> Convert.FromBase64String
readBlock String.Empty
|> PemUtility.PemToByteArray
|> Some
}
| _ ->
Expand Down
13 changes: 3 additions & 10 deletions NOnion/Directory/HiddenServiceSecondLayerDescriptorDocument.fs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type HiddenServiceSecondLayerDescriptorDocument =
let lines = stringToParse.Split '\n' |> MutableQueue<string>

let rec readBlock(state: string) =
let line = lines.Dequeue()
let line = sprintf "%s\n" (lines.Dequeue())

if line.StartsWith "-----END" then
state + line
Expand All @@ -40,17 +40,10 @@ type HiddenServiceSecondLayerDescriptorDocument =
| "encrypted" ->
lines.Dequeue() |> ignore<string>

let payloadString = readBlock String.Empty

{ state with
HiddenServiceSecondLayerDescriptorDocument.EncryptedPayload =
payloadString
.Replace(
"-----BEGIN MESSAGE-----",
String.Empty
)
.Replace("-----END MESSAGE-----", String.Empty)
|> Convert.FromBase64String
readBlock String.Empty
|> PemUtility.PemToByteArray
|> Some
}
| _ ->
Expand Down
Loading