Skip to content

Commit bc110ef

Browse files
Feature/context extendeddata (#230)
* Add extendedData to CiphertextElectionContext * Add a simple linked list implementation * use c style type names * return error codes * add election context C test rename refactor linked list to remove electionguard from function names * add external api exports and get function * rework tests * move logic into code file * move struct implement to c file make the external typedef struct opaque to the caller. add more api methods. refactor tests * refactor C function name add api documentation. * Add C# native interface for LinkedList add the C# facade class and unit tests. * Add ExtendedData to C# CiphertextElectionContext add the native interface binding, add the new field to the existing c# facade. add unit test. * add stdint to header * fix assertion use in main lib * add missing comma * address pr feedback * increment version
1 parent e1d4325 commit bc110ef

19 files changed

Lines changed: 918 additions & 28 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ set(META_PROJECT_EXPORT "ElectionGuard")
77
set(META_PROJECT_TARGET "electionguard")
88
set(META_VERSION_MAJOR "0")
99
set(META_VERSION_MINOR "1")
10-
set(META_VERSION_PATCH "3")
10+
set(META_VERSION_PATCH "5")
1111
set(META_VERSION "${META_VERSION_MAJOR}.${META_VERSION_MINOR}.${META_VERSION_PATCH}")
1212

1313
set(LIBRARY_PUBLIC_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include)
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System;
2+
using System.Diagnostics;
3+
using NUnit.Framework;
4+
5+
namespace ElectionGuard.Encrypt.Tests
6+
{
7+
[TestFixture]
8+
public class TestCollections
9+
{
10+
[Test]
11+
public void Test_Can_Create_Linked_list()
12+
{
13+
// Arrange
14+
var list = new LinkedList();
15+
16+
// Act
17+
list.Append("some", "value");
18+
list.Append("another", "thing");
19+
20+
var firstValue = list.GetValueAt(0);
21+
var secondValue = list.GetValueAt(1);
22+
23+
// Assert
24+
Assert.That(firstValue == "value");
25+
Assert.That(secondValue == "thing");
26+
}
27+
}
28+
}

bindings/netstandard/ElectionGuard/ElectionGuard.Encryption.Tests/TestElection.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,24 @@ public void Test_Can_Deserialize_Ciphertext_Election_Context()
2020
Assert.That(result.CommitmentHash.ToHex() == "02");
2121
Assert.That(result.ManifestHash.ToHex() == "02");
2222
}
23+
24+
[Test]
25+
public void Test_Can_Assign_Extended_Data_To_Ciphertext_Election_Context()
26+
{
27+
// Arrange
28+
var extendedData = new LinkedList();
29+
extendedData.Append("ballot_base_uri", "http://something.vote/");
30+
31+
// Act
32+
var context = new CiphertextElectionContext(
33+
3, 2,
34+
Constants.ONE_MOD_P, Constants.ONE_MOD_Q, Constants.ONE_MOD_Q,
35+
extendedData);
36+
37+
var cachedValue = context.ExtendedData.GetValueAt(0);
38+
39+
// Assert
40+
Assert.That(cachedValue == "http://something.vote/");
41+
}
2342
}
2443
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
4+
namespace ElectionGuard
5+
{
6+
using NativeLinkedList = NativeInterface.LinkedList.LinkedListHandle;
7+
8+
/// <Summary>
9+
/// A singly-linked list data structure composed of strings for keys and strings for values.
10+
/// </Summary>
11+
public class LinkedList : DisposableBase
12+
{
13+
/// <Summary>
14+
/// Get the count of elements in the list.
15+
/// </Summary>
16+
public unsafe ulong Count
17+
{
18+
get
19+
{
20+
return NativeInterface.LinkedList.GetCount(Handle);
21+
}
22+
}
23+
24+
internal unsafe NativeLinkedList Handle;
25+
26+
unsafe internal LinkedList(NativeLinkedList handle)
27+
{
28+
Handle = handle;
29+
}
30+
31+
unsafe public LinkedList()
32+
{
33+
var status = NativeInterface.LinkedList.New(out Handle);
34+
status.ThrowIfError();
35+
}
36+
37+
/// <summary>
38+
/// Append the key value pair to the end of the linked list
39+
/// </summary>
40+
public unsafe void Append(string key, string value)
41+
{
42+
var status = NativeInterface.LinkedList.Append(Handle, key, value);
43+
status.ThrowIfError();
44+
}
45+
46+
/// <summary>
47+
/// Delete the last value in the list
48+
/// </summary>
49+
public unsafe void DeleteLast()
50+
{
51+
var status = NativeInterface.LinkedList.DeleteLast(Handle);
52+
status.ThrowIfError();
53+
}
54+
55+
/// <summary>
56+
/// Get the element at the designated position
57+
/// </summary>
58+
public unsafe Tuple<string, string> GetElementAt(ulong position)
59+
{
60+
var status = NativeInterface.LinkedList.GetElementAt(
61+
Handle, position, out IntPtr key, out IntPtr value);
62+
status.ThrowIfError();
63+
return Tuple.Create(Marshal.PtrToStringAnsi(key), Marshal.PtrToStringAnsi(value));
64+
}
65+
66+
/// <summary>
67+
/// Get the value at the designated position
68+
/// </summary>
69+
public unsafe string GetValueAt(ulong position)
70+
{
71+
var status = NativeInterface.LinkedList.GetValueAt(
72+
Handle, position, out IntPtr value);
73+
status.ThrowIfError();
74+
return Marshal.PtrToStringAnsi(value);
75+
}
76+
77+
protected override unsafe void DisposeUnmanaged()
78+
{
79+
base.DisposeUnmanaged();
80+
81+
if (Handle == null || Handle.IsInvalid) return;
82+
Handle.Dispose();
83+
Handle = null;
84+
}
85+
}
86+
}

bindings/netstandard/ElectionGuard/ElectionGuard.Encryption/Election.cs

Lines changed: 56 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ namespace ElectionGuard
66
using NativeCiphertextElectionContext = NativeInterface.CiphertextElectionContext.CiphertextElectionContextHandle;
77
using NativeElementModP = NativeInterface.ElementModP.ElementModPHandle;
88
using NativeElementModQ = NativeInterface.ElementModQ.ElementModQHandle;
9+
using NativeLinkedList = NativeInterface.LinkedList.LinkedListHandle;
910

1011

1112
/// <summary>
@@ -112,29 +113,74 @@ public unsafe ElementModQ CryptoExtendedBaseHash
112113
}
113114
}
114115

116+
/// <summary>
117+
/// Get a linked list containing the extended data of the election.
118+
/// </summary>
119+
public unsafe LinkedList ExtendedData
120+
{
121+
get
122+
{
123+
var status = NativeInterface.CiphertextElectionContext.GetExtendedData(
124+
Handle, out NativeLinkedList value);
125+
if (status != Status.ELECTIONGUARD_STATUS_SUCCESS)
126+
{
127+
Console.WriteLine($"GetExtendedData Error Status: {status}");
128+
return null;
129+
}
130+
return new LinkedList(value);
131+
}
132+
}
133+
115134
internal unsafe NativeCiphertextElectionContext Handle;
116135

117136
public unsafe CiphertextElectionContext(string json)
118137
{
119138
var status = NativeInterface.CiphertextElectionContext.FromJson(json, out Handle);
120-
if (status != Status.ELECTIONGUARD_STATUS_SUCCESS)
121-
{
122-
Console.WriteLine($"CiphertextElectionContext Error Status: {status}");
123-
}
139+
status.ThrowIfError();
124140
}
125141

142+
/// <summary>
143+
/// Makes a CiphertextElectionContext object.
144+
///
145+
/// <param name="number_of_guardians"> The number of guardians necessary to generate the public key </param>
146+
/// <param name="quorum"> The quorum of guardians necessary to decrypt an election. Must be less than `number_of_guardians` </param>
147+
/// <param name="publicKey"> the public key of the election </param>
148+
/// <param name="commitmentHash"> the hash of the commitments the guardians make to each other </param>
149+
/// <param name="manifestHash"> the hash of the election metadata </param>
150+
/// </summary>
126151
public unsafe CiphertextElectionContext(ulong numberOfGuardians,
127152
ulong quorum,
128153
ElementModP publicKey,
129154
ElementModQ commitmentHash,
130155
ElementModQ manifestHash)
131156
{
132157
var status = NativeInterface.CiphertextElectionContext.Make(
133-
numberOfGuardians, quorum, publicKey.Handle, commitmentHash.Handle, manifestHash.Handle, out Handle);
134-
if (status != Status.ELECTIONGUARD_STATUS_SUCCESS)
135-
{
136-
Console.WriteLine($"CiphertextElectionContext Error Status: {status}");
137-
}
158+
numberOfGuardians, quorum, publicKey.Handle,
159+
commitmentHash.Handle, manifestHash.Handle, out Handle);
160+
status.ThrowIfError();
161+
}
162+
163+
/// <summary>
164+
/// Makes a CiphertextElectionContext object.
165+
///
166+
/// <param name="numberOfGuardians"> The number of guardians necessary to generate the public key </param>
167+
/// <param name="quorum"> The quorum of guardians necessary to decrypt an election. Must be less than `number_of_guardians` </param>
168+
/// <param name="publicKey"> the public key of the election </param>
169+
/// <param name="commitmentHash"> the hash of the commitments the guardians make to each other </param>
170+
/// <param name="manifestHash"> the hash of the election metadata </param>
171+
/// <param name="extendedData"> an unordered map of key value strings revelant to the consuming application </param>
172+
/// </summary>
173+
public unsafe CiphertextElectionContext(ulong numberOfGuardians,
174+
ulong quorum,
175+
ElementModP publicKey,
176+
ElementModQ commitmentHash,
177+
ElementModQ manifestHash,
178+
LinkedList extendedData)
179+
{
180+
var status = NativeInterface.CiphertextElectionContext.Make(
181+
numberOfGuardians, quorum, publicKey.Handle,
182+
commitmentHash.Handle, manifestHash.Handle, extendedData.Handle, out Handle);
183+
status.ThrowIfError();
138184
}
139185

140186
protected override unsafe void DisposeUnmanaged()
@@ -153,11 +199,7 @@ public unsafe string ToJson()
153199
{
154200
var status = NativeInterface.CiphertextElectionContext.ToJson(
155201
Handle, out IntPtr pointer, out ulong size);
156-
if (status != Status.ELECTIONGUARD_STATUS_SUCCESS)
157-
{
158-
Console.WriteLine($"ToJson Error Status: {status}");
159-
return null;
160-
}
202+
status.ThrowIfError();
161203
var json = Marshal.PtrToStringAnsi(pointer);
162204
return json;
163205
}

bindings/netstandard/ElectionGuard/ElectionGuard.Encryption/ElectionGuard.Encryption.csproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
<!-- Project -->
88
<RootNamespace>ElectionGuard.Encryption</RootNamespace>
99
<AssemblyName>ElectionGuard.Encryption</AssemblyName>
10-
<Version>0.1.4</Version>
11-
<AssemblyVersion>0.1.4.0</AssemblyVersion>
12-
<AssemblyFileVersion>0.1.4.0</AssemblyFileVersion>
10+
<Version>0.1.5</Version>
11+
<AssemblyVersion>0.1.5.0</AssemblyVersion>
12+
<AssemblyFileVersion>0.1.5.0</AssemblyFileVersion>
1313
</PropertyGroup>
1414

1515
<PropertyGroup>
@@ -19,7 +19,7 @@
1919
<Title>ElectionGuard Encryption</Title>
2020
<Description>Open source implementation of ElectionGuard's ballot encryption.</Description>
2121
<Authors>Microsoft</Authors>
22-
<PackageVersion>0.1.4</PackageVersion>
22+
<PackageVersion>0.1.5</PackageVersion>
2323
<PackageLicenseExpression>MIT</PackageLicenseExpression>
2424
<PackageProjectUrl>https://github.com/microsoft/electionguard-cpp</PackageProjectUrl>
2525
<RepositoryUrl>https://github.com/microsoft/electionguard-cpp</RepositoryUrl>

bindings/netstandard/ElectionGuard/ElectionGuard.Encryption/NativeInterface.cs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,71 @@ internal static unsafe class NativeInterface
150150

151151
internal unsafe struct CharPtr { };
152152

153+
#region Collections
154+
155+
internal static unsafe class LinkedList
156+
{
157+
internal unsafe struct LinkedListType { };
158+
159+
internal class LinkedListHandle
160+
: ElectionguardSafeHandle<LinkedListType>
161+
{
162+
protected override bool Free()
163+
{
164+
if (IsClosed) return true;
165+
166+
var status = LinkedList.Free(TypedPtr);
167+
if (status != Status.ELECTIONGUARD_STATUS_SUCCESS)
168+
{
169+
Console.WriteLine($"LinkedList Error Free: {status}");
170+
return false;
171+
}
172+
return true;
173+
}
174+
}
175+
176+
[DllImport(DllName, EntryPoint = "eg_linked_list_new",
177+
CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
178+
internal static extern Status New(out LinkedListHandle handle);
179+
180+
[DllImport(DllName, EntryPoint = "eg_linked_list_free",
181+
CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
182+
internal static extern Status Free(LinkedListType* handle);
183+
184+
[DllImport(DllName, EntryPoint = "eg_linked_list_append",
185+
CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
186+
internal static extern Status Append(
187+
LinkedListHandle handle,
188+
[MarshalAs(UnmanagedType.LPStr)] string key,
189+
[MarshalAs(UnmanagedType.LPStr)] string value);
190+
191+
[DllImport(DllName, EntryPoint = "eg_linked_list_delete_last",
192+
CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
193+
internal static extern Status DeleteLast(LinkedListHandle handle);
194+
195+
[DllImport(DllName, EntryPoint = "eg_linked_list_get_count",
196+
CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
197+
internal static extern ulong GetCount(
198+
LinkedListHandle handle);
199+
200+
[DllImport(DllName, EntryPoint = "eg_linked_list_get_element_at",
201+
CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
202+
internal static extern Status GetElementAt(
203+
LinkedListHandle handle,
204+
ulong position,
205+
out IntPtr key,
206+
out IntPtr value);
207+
208+
[DllImport(DllName, EntryPoint = "eg_linked_list_get_value_at",
209+
CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
210+
internal static extern Status GetValueAt(
211+
LinkedListHandle handle,
212+
ulong position,
213+
out IntPtr value);
214+
}
215+
216+
#endregion
217+
153218
#region Group
154219

155220
internal static unsafe class ElementModP
@@ -1936,6 +2001,13 @@ internal static extern Status GetCryptoExtendedBaseHash(
19362001
CiphertextElectionContextHandle handle,
19372002
out ElementModQ.ElementModQHandle crypto_extended_base_hash);
19382003

2004+
[DllImport(DllName,
2005+
EntryPoint = "eg_ciphertext_election_context_get_extended_data",
2006+
CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
2007+
internal static extern Status GetExtendedData(
2008+
CiphertextElectionContextHandle handle,
2009+
out LinkedList.LinkedListHandle extended_data);
2010+
19392011
[DllImport(DllName, EntryPoint = "eg_ciphertext_election_context_make",
19402012
CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
19412013
internal static extern Status Make(
@@ -1946,6 +2018,27 @@ internal static extern Status Make(
19462018
ElementModQ.ElementModQHandle manifest_hash,
19472019
out CiphertextElectionContextHandle handle);
19482020

2021+
[DllImport(DllName, EntryPoint = "eg_ciphertext_election_context_make_with_extended_data",
2022+
CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
2023+
internal static extern Status Make(
2024+
ulong number_of_guardians,
2025+
ulong quorum,
2026+
ElementModP.ElementModPHandle elgamal_public_key,
2027+
ElementModQ.ElementModQHandle commitment_hash,
2028+
ElementModQ.ElementModQHandle manifest_hash,
2029+
LinkedList.LinkedListHandle extended_data,
2030+
out CiphertextElectionContextHandle handle);
2031+
2032+
[DllImport(DllName, EntryPoint = "eg_ciphertext_election_context_make_from_hex",
2033+
CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
2034+
internal static extern Status Make(
2035+
ulong number_of_guardians,
2036+
ulong quorum,
2037+
[MarshalAs(UnmanagedType.LPStr)] string hex_elgamal_public_key,
2038+
[MarshalAs(UnmanagedType.LPStr)] string hex_commitment_hash,
2039+
[MarshalAs(UnmanagedType.LPStr)] string hex_manifest_hash,
2040+
out CiphertextElectionContextHandle handle);
2041+
19492042
[DllImport(DllName, EntryPoint = "eg_ciphertext_election_context_make_from_hex",
19502043
CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
19512044
internal static extern Status Make(
@@ -1954,6 +2047,7 @@ internal static extern Status Make(
19542047
[MarshalAs(UnmanagedType.LPStr)] string hex_elgamal_public_key,
19552048
[MarshalAs(UnmanagedType.LPStr)] string hex_commitment_hash,
19562049
[MarshalAs(UnmanagedType.LPStr)] string hex_manifest_hash,
2050+
LinkedList.LinkedListHandle extended_data,
19572051
out CiphertextElectionContextHandle handle);
19582052

19592053
[DllImport(DllName, EntryPoint = "eg_ciphertext_election_context_from_json",

0 commit comments

Comments
 (0)