Skip to content

Commit 33042a9

Browse files
author
Jesper Glintborg
committedJul 16, 2020
Initial commit.
0 parents  commit 33042a9

10 files changed

+342
-0
lines changed
 

‎.gitattributes

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Auto detect text files and perform LF normalization
2+
* text=auto
3+
4+
# Custom for Visual Studio
5+
*.cs diff=csharp
6+
*.sln merge=union
7+
*.csproj merge=union
8+
*.vbproj merge=union
9+
*.fsproj merge=union
10+
*.dbproj merge=union
11+
12+
# Standard to msysgit
13+
*.doc diff=astextplain
14+
*.DOC diff=astextplain
15+
*.docx diff=astextplain
16+
*.DOCX diff=astextplain
17+
*.dot diff=astextplain
18+
*.DOT diff=astextplain
19+
*.pdf diff=astextplain
20+
*.PDF diff=astextplain
21+
*.rtf diff=astextplain
22+
*.RTF diff=astextplain

‎.gitignore

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Ignore Windows thumbnails
2+
Thumbs.db
3+
4+
# Ignore Visual Studio files
5+
*.obj
6+
*.exe
7+
*.pdb
8+
*.nupkg
9+
*.user
10+
*.aps
11+
*.pch
12+
*.vspscc
13+
*_i.c
14+
*_p.c
15+
*.ncb
16+
*.suo
17+
*.tlb
18+
*.tlh
19+
*.bak
20+
*.cache
21+
*.ilk
22+
*.log
23+
*.orig
24+
[Bb]in
25+
[Dd]ebug*/
26+
*.lib
27+
*.sbr
28+
obj/
29+
[Rr]elease*/
30+
_ReSharper*/
31+
*.DotSettings
32+
[Tt]est[Rr]esult*
33+
34+
# Ignore MonoDevelop files
35+
*.userprefs
36+
37+
# Ignore NUnit project files
38+
*.nunit
39+
40+
# Ignore NuGet Packages
41+
/src/packages/
42+
43+
#Ignore VS files
44+
.vs/
45+
46+
#Ignore lock files
47+
*.lock.json
48+
.idea/

‎NuGet.Config

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<configuration>
3+
<packageSources>
4+
<add key="NuGet.org" value="https://api.nuget.org/v3/index.json" />
5+
<add key="xunit" value="https://www.myget.org/F/xunit/api/v3/index.json" />
6+
</packageSources>
7+
</configuration>

‎src/NetMQSecurityFactory.sln

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.30104.148
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{6AB1E02C-7800-4934-AA7A-4161459E1278}"
7+
ProjectSection(SolutionItems) = preProject
8+
..\.gitattributes = ..\.gitattributes
9+
..\.gitignore = ..\.gitignore
10+
Directory.Build.props = Directory.Build.props
11+
Directory.Build.targets = Directory.Build.targets
12+
EndProjectSection
13+
EndProject
14+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetMQSecurityFactory", "NetMQSecurityFactory\NetMQSecurityFactory.csproj", "{D6F112AA-46B7-4312-A8C2-8E8972C4B1FC}"
15+
EndProject
16+
Global
17+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
18+
Debug|Any CPU = Debug|Any CPU
19+
Debug|x64 = Debug|x64
20+
Debug|x86 = Debug|x86
21+
Release|Any CPU = Release|Any CPU
22+
Release|x64 = Release|x64
23+
Release|x86 = Release|x86
24+
EndGlobalSection
25+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
26+
{D6F112AA-46B7-4312-A8C2-8E8972C4B1FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27+
{D6F112AA-46B7-4312-A8C2-8E8972C4B1FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
28+
{D6F112AA-46B7-4312-A8C2-8E8972C4B1FC}.Debug|x64.ActiveCfg = Debug|Any CPU
29+
{D6F112AA-46B7-4312-A8C2-8E8972C4B1FC}.Debug|x64.Build.0 = Debug|Any CPU
30+
{D6F112AA-46B7-4312-A8C2-8E8972C4B1FC}.Debug|x86.ActiveCfg = Debug|Any CPU
31+
{D6F112AA-46B7-4312-A8C2-8E8972C4B1FC}.Debug|x86.Build.0 = Debug|Any CPU
32+
{D6F112AA-46B7-4312-A8C2-8E8972C4B1FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
33+
{D6F112AA-46B7-4312-A8C2-8E8972C4B1FC}.Release|Any CPU.Build.0 = Release|Any CPU
34+
{D6F112AA-46B7-4312-A8C2-8E8972C4B1FC}.Release|x64.ActiveCfg = Release|Any CPU
35+
{D6F112AA-46B7-4312-A8C2-8E8972C4B1FC}.Release|x64.Build.0 = Release|Any CPU
36+
{D6F112AA-46B7-4312-A8C2-8E8972C4B1FC}.Release|x86.ActiveCfg = Release|Any CPU
37+
{D6F112AA-46B7-4312-A8C2-8E8972C4B1FC}.Release|x86.Build.0 = Release|Any CPU
38+
EndGlobalSection
39+
GlobalSection(SolutionProperties) = preSolution
40+
HideSolutionNode = FALSE
41+
EndGlobalSection
42+
GlobalSection(ExtensibilityGlobals) = postSolution
43+
SolutionGuid = {634B21AA-6698-4925-A0A3-943100197AB7}
44+
EndGlobalSection
45+
EndGlobal
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
using System.Reflection;
6+
7+
namespace NetMQSecurityFactory
8+
{
9+
public static class EncryptionFactory
10+
{
11+
private static Container<ICurveEncrypt> CurveEncrypt;
12+
13+
static EncryptionFactory()
14+
{
15+
LoadPlugins();
16+
}
17+
18+
public static void LoadPlugins()
19+
{
20+
CurveEncrypt = LoadPluginsOfType<ICurveEncrypt>();
21+
}
22+
23+
private static Container<T> LoadPluginsOfType<T>() where T : class
24+
{
25+
var type = typeof(T);
26+
var path = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
27+
var assemblies = Directory.GetFiles(path, "*.dll");
28+
var encryptorTypes = new List<Type>();
29+
30+
foreach (var assemblyName in assemblies)
31+
{
32+
try
33+
{
34+
var assembly = Assembly.LoadFrom(assemblyName);
35+
if (assembly != null)
36+
{
37+
encryptorTypes.AddRange(assembly.GetTypes().Where(p => type.IsAssignableFrom(p) && p.IsAbstract == false));
38+
}
39+
}
40+
catch (Exception)
41+
{
42+
}
43+
}
44+
45+
var fallback = encryptorTypes.First(x => EncryptionFallback(x));
46+
var priority = encryptorTypes.FirstOrDefault(x => EncryptionPriority(x));
47+
return new Container<T>(priority, fallback);
48+
}
49+
50+
private class Container<T> where T : class
51+
{
52+
private Type priority;
53+
private Type fallback;
54+
55+
public Container(Type priority, Type fallback)
56+
{
57+
this.priority = priority;
58+
this.fallback = fallback;
59+
}
60+
61+
public T CreateInstance()
62+
{
63+
try
64+
{
65+
if (priority != null)
66+
{
67+
return Activator.CreateInstance(priority) as T;
68+
}
69+
}
70+
catch (Exception e)
71+
{
72+
priority = null;
73+
}
74+
return Activator.CreateInstance(fallback) as T;
75+
}
76+
}
77+
78+
private static bool EncryptionPriority(Type t)
79+
{
80+
var priorityAttributes = (EncryptionPriorityAttribute[])t.GetCustomAttributes(typeof(EncryptionPriorityAttribute), false);
81+
return (priorityAttributes.Length > 0);
82+
}
83+
84+
private static bool EncryptionFallback(Type t)
85+
{
86+
var priorityAttributes = (EncryptionFallbackAttribute[])t.GetCustomAttributes(typeof(EncryptionFallbackAttribute), false);
87+
return (priorityAttributes.Length > 0);
88+
}
89+
90+
static public ICurveEncrypt GetCurveEncryptor(ReadOnlySpan<byte> secretKey, ReadOnlySpan<byte> publicKey)
91+
{
92+
ICurveEncrypt encryptor = null;
93+
if (CurveEncrypt != null)
94+
{
95+
encryptor = CurveEncrypt.CreateInstance();
96+
encryptor?.SetKey(secretKey, publicKey);
97+
}
98+
return encryptor;
99+
}
100+
}
101+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using System;
2+
3+
namespace NetMQSecurityFactory
4+
{
5+
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
6+
public class EncryptionFallbackAttribute : System.Attribute
7+
{
8+
}
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using System;
2+
3+
namespace NetMQSecurityFactory
4+
{
5+
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
6+
public class EncryptionPriorityAttribute : System.Attribute
7+
{
8+
}
9+
}
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System;
2+
3+
namespace NetMQSecurityFactory
4+
{
5+
public interface ICurveEncrypt : IDisposable
6+
{
7+
void SetKey(ReadOnlySpan<byte> secretKey, ReadOnlySpan<byte> publicKey);
8+
void Encrypt(Span<byte> cipher, Span<byte> mac, ReadOnlySpan<byte> message, ReadOnlySpan<byte> nonce);
9+
void Encrypt(Span<byte> cipher, ReadOnlySpan<byte> message, ReadOnlySpan<byte> nonce);
10+
bool TryDecrypt(Span<byte> message, ReadOnlySpan<byte> cipher, ReadOnlySpan<byte> nonce);
11+
bool TryDecrypt(Span<byte> message, ReadOnlySpan<byte> cipher, ReadOnlySpan<byte> mac, ReadOnlySpan<byte> nonce);
12+
}
13+
}

‎src/NetMQSecurityFactory/LibSodium.cs

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
4+
namespace NetMQSecurityFactory
5+
{
6+
[EncryptionPriority]
7+
public class LibSodium : ICurveEncrypt
8+
{
9+
private byte[] SharedSecretKey = new byte[32];
10+
const string DllName = "libsodium.dll";
11+
12+
//crypto_secretbox_easy
13+
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
14+
internal static extern int crypto_secretbox_easy(ref byte buffer, byte[] message, long messageLength, byte[] nonce, byte[] key);
15+
16+
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
17+
internal static extern int crypto_box_beforenm(byte[] shared_key, byte[] public_key, byte[] secret_key);
18+
19+
//crypto_secretbox_open_easy
20+
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
21+
internal static extern int crypto_secretbox_open_easy(ref byte buffer, byte[] cipherText, long cipherTextLength, byte[] nonce, byte[] key);
22+
23+
//sodium_version_string
24+
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
25+
internal static extern IntPtr sodium_version_string();
26+
27+
public LibSodium()
28+
{
29+
var ptr = LibSodium.sodium_version_string();
30+
Marshal.PtrToStringAnsi(ptr);
31+
}
32+
33+
public void Dispose()
34+
{
35+
}
36+
37+
public void SetKey(ReadOnlySpan<byte> secretKey, ReadOnlySpan<byte> publicKey)
38+
{
39+
crypto_box_beforenm( SharedSecretKey,publicKey.ToArray(), secretKey.ToArray());
40+
}
41+
42+
public void Encrypt(Span<byte> cipher, Span<byte> mac, ReadOnlySpan<byte> message, ReadOnlySpan<byte> nonce)
43+
{
44+
var complete = new Span<byte>( new byte[mac.Length+cipher.Length]);
45+
46+
LibSodium.crypto_secretbox_easy(ref cipher.GetPinnableReference(), complete.ToArray(), complete.Length, nonce.ToArray(), SharedSecretKey);
47+
48+
complete.Slice(0, mac.Length).CopyTo(mac);
49+
complete.Slice(mac.Length).CopyTo(cipher);
50+
}
51+
52+
public void Encrypt(Span<byte> cipher, ReadOnlySpan<byte> message, ReadOnlySpan<byte> nonce)
53+
{
54+
LibSodium.crypto_secretbox_easy(ref cipher.GetPinnableReference(), message.ToArray(), message.Length, nonce.ToArray(), SharedSecretKey);
55+
}
56+
57+
public bool TryDecrypt(Span<byte> message, ReadOnlySpan<byte> cipher, ReadOnlySpan<byte> nonce)
58+
{
59+
return LibSodium.crypto_secretbox_open_easy(ref message.GetPinnableReference(), cipher.ToArray(), cipher.Length, nonce.ToArray(), SharedSecretKey) == 0;
60+
}
61+
62+
public bool TryDecrypt(Span<byte> message, ReadOnlySpan<byte> cipher, ReadOnlySpan<byte> mac, ReadOnlySpan<byte> nonce)
63+
{
64+
var complete = new Span<byte>(new byte[mac.Length + cipher.Length]);
65+
mac.CopyTo(complete);
66+
67+
cipher.CopyTo(complete.Slice(mac.Length));
68+
69+
return LibSodium.crypto_secretbox_open_easy(ref message.GetPinnableReference(), complete.ToArray(), complete.Length, nonce.ToArray(), SharedSecretKey) == 0;
70+
}
71+
}
72+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFrameworks>net45;net47;netstandard2.0;netstandard2.1</TargetFrameworks>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies.net47" Version="1.0.0">
9+
<PrivateAssets>all</PrivateAssets>
10+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
11+
</PackageReference>
12+
<PackageReference Include="System.AppContext" Version="4.3.0" />
13+
<PackageReference Include="System.Memory" Version="4.5.3" />
14+
</ItemGroup>
15+
16+
</Project>

0 commit comments

Comments
 (0)
Please sign in to comment.