diff --git a/Manifest.toml b/Manifest.toml index 989b629..44ca0b2 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -3,21 +3,49 @@ [[Base64]] uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" +[[BinDeps]] +deps = ["Compat", "Libdl", "SHA", "URIParser"] +git-tree-sha1 = "12093ca6cdd0ee547c39b1870e0c9c3f154d9ca9" +uuid = "9e28174c-4ba2-5203-b857-d8d62c4213ee" +version = "0.8.10" + +[[BinaryProvider]] +deps = ["Libdl", "Logging", "SHA"] +git-tree-sha1 = "ecdec412a9abc8db54c0efc5548c64dfce072058" +uuid = "b99e7846-7c00-51b0-8f62-c81ae34c0232" +version = "0.5.10" + [[BitConverter]] git-tree-sha1 = "5274a781a2e71cfb9a2083dfcd2ca5318716a660" uuid = "3a3ce9e8-98e7-11e9-0fa0-055639f146d3" version = "0.1.1" +[[Compat]] +deps = ["Base64", "Dates", "DelimitedFiles", "Distributed", "InteractiveUtils", "LibGit2", "Libdl", "LinearAlgebra", "Markdown", "Mmap", "Pkg", "Printf", "REPL", "Random", "Serialization", "SharedArrays", "Sockets", "SparseArrays", "Statistics", "Test", "UUIDs", "Unicode"] +git-tree-sha1 = "b0b7e8a0d054fada22b64095b46469627a138943" +uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" +version = "2.2.1" + [[CryptoGroups]] deps = ["BitConverter", "ECC", "Mods", "Paillier", "Primes", "Random"] git-tree-sha1 = "85c8ff8078d384a7d7c1ce22cc255f698731eed7" uuid = "bc997328-bedd-407e-bcd3-5758e064a52d" version = "0.1.2" +[[CryptoSignatures]] +deps = ["CryptoGroups", "Random"] +git-tree-sha1 = "6d27f5ca22a87e7acc30cca60e7a637b96e04eaf" +uuid = "35cc5888-0c46-470e-89c7-eafcaf79a1aa" +version = "0.2.2" + [[Dates]] deps = ["Printf"] uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" +[[DelimitedFiles]] +deps = ["Mmap"] +uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab" + [[DiffieHellman]] deps = ["CryptoGroups"] git-tree-sha1 = "a16ae95af764fa991b031504824b40ce21551a08" @@ -34,27 +62,10 @@ git-tree-sha1 = "ebff856a4057ad7dbb4648bf3d4c7f9e4bc35e97" uuid = "a99b485a-c5c8-540e-ab00-7a7265134077" version = "0.2.3" -[[ExprTools]] -git-tree-sha1 = "6f0517056812fd6aa3af23d4b70d5325a2ae4e95" -uuid = "e2ba6199-217a-4e67-a87a-7c52f15ade04" -version = "0.1.1" - -[[EzXML]] -deps = ["Printf", "XML2_jll"] -git-tree-sha1 = "0fa3b52a04a4e210aeb1626def9c90df3ae65268" -uuid = "8f5d6c58-4d21-5cfd-889c-e3ad7ee6a615" -version = "1.1.0" - [[InteractiveUtils]] deps = ["Markdown"] uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" -[[Intervals]] -deps = ["Dates", "Printf", "RecipesBase", "Serialization", "TimeZones"] -git-tree-sha1 = "9da845579d1dce4ce5118008c3fe6df17260bb46" -uuid = "d8418881-c3e1-53bb-8760-2df7ec849ed5" -version = "1.4.2" - [[LibGit2]] deps = ["Printf"] uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" @@ -62,12 +73,6 @@ uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" [[Libdl]] uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" -[[Libiconv_jll]] -deps = ["Libdl", "Pkg"] -git-tree-sha1 = "7c36dfe7971e55da03d8f54b67d4b3fb8ee01d63" -uuid = "94ce4f54-9a6c-5748-9c1c-f9c7231a4531" -version = "1.16.0+6" - [[LinearAlgebra]] deps = ["Libdl"] uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" @@ -79,11 +84,8 @@ uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" deps = ["Base64"] uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" -[[Mocking]] -deps = ["ExprTools"] -git-tree-sha1 = "916b850daad0d46b8c71f65f719c49957e9513ed" -uuid = "78c3b35d-d492-501b-9361-3d52fe80e533" -version = "0.7.1" +[[Mmap]] +uuid = "a63ad114-7e13-5084-954f-fe012c677804" [[Mods]] deps = ["Test"] @@ -96,10 +98,11 @@ git-tree-sha1 = "262b92184325959e231a93ec5acd61b29b20d237" uuid = "d8f48be2-8af9-45f0-b400-11a6372d221d" version = "0.3.1" -[[OffsetArrays]] -git-tree-sha1 = "b8500f9d73999cfbab4add5136ec26894081581e" -uuid = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" -version = "1.1.3" +[[Nettle]] +deps = ["BinDeps", "BinaryProvider", "Libdl", "Test"] +git-tree-sha1 = "f57e8e907faab4f55f9f164313a633509ac83e2c" +uuid = "49dea1ee-f6fa-5aa6-9a11-8816cee7d4b9" +version = "0.4.0" [[Paillier]] deps = ["Polynomials", "Primes", "Random"] @@ -107,15 +110,21 @@ git-tree-sha1 = "4da59ccc00548b8765b74909f7be4be998eab061" uuid = "84e01822-a062-59e4-8289-aa032edeecdd" version = "0.2.4" +[[PeaceCypher]] +deps = ["CryptoGroups", "CryptoSignatures", "DiffieHellman", "Nettle", "Pkg", "Random", "SecureIO", "Sockets"] +git-tree-sha1 = "c0b33dcb6190d4c8ac5b42efc8101a796e5ca70a" +uuid = "7743456c-e0c5-4477-a2b6-196c240b0368" +version = "0.3.3" + [[Pkg]] deps = ["Dates", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "UUIDs"] uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" [[Polynomials]] -deps = ["Intervals", "LinearAlgebra", "OffsetArrays", "RecipesBase"] -git-tree-sha1 = "7ce1a60df1a8eb61df4cef5698abc9a18575c91f" +deps = ["LinearAlgebra", "RecipesBase"] +git-tree-sha1 = "1185511cac8ab9d0b658b663eae34fe9a95d4332" uuid = "f27b6e38-b328-58d1-80ce-0feddd5e7a45" -version = "1.1.7" +version = "0.6.1" [[Primes]] deps = ["Test"] @@ -136,28 +145,46 @@ deps = ["Serialization"] uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" [[RecipesBase]] -git-tree-sha1 = "58de8f7e33b7fda6ee39eff65169cd1e19d0c107" +git-tree-sha1 = "b4ed4a7f988ea2340017916f7c9e5d7560b52cae" uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" -version = "1.0.2" +version = "0.8.0" [[SHA]] uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" +[[SecureIO]] +deps = ["Nettle"] +git-tree-sha1 = "983245bb187058eee0f27c8cdfee7b60d18e5b01" +uuid = "ee77041e-65ec-469d-b516-892ca52996d6" +version = "0.3.0" + [[Serialization]] uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" +[[SharedArrays]] +deps = ["Distributed", "Mmap", "Random", "Serialization"] +uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383" + [[Sockets]] uuid = "6462fe0b-24de-5631-8697-dd941f90decc" +[[SparseArrays]] +deps = ["LinearAlgebra", "Random"] +uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" + +[[Statistics]] +deps = ["LinearAlgebra", "SparseArrays"] +uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" + [[Test]] deps = ["Distributed", "InteractiveUtils", "Logging", "Random"] uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" -[[TimeZones]] -deps = ["Dates", "EzXML", "Mocking", "Pkg", "Printf", "RecipesBase", "Serialization", "Unicode"] -git-tree-sha1 = "338ddbb2b9b50a9a423ba6c3fad1824553535988" -uuid = "f269a46b-ccf7-5d73-abea-4c690281aa53" -version = "1.3.2" +[[URIParser]] +deps = ["Unicode"] +git-tree-sha1 = "53a9f49546b8d2dd2e688d216421d050c9a31d0d" +uuid = "30578b45-9adc-5946-b283-645ec420af67" +version = "0.4.1" [[UUIDs]] deps = ["Random", "SHA"] @@ -165,15 +192,3 @@ uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" [[Unicode]] uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" - -[[XML2_jll]] -deps = ["Libdl", "Libiconv_jll", "Pkg", "Zlib_jll"] -git-tree-sha1 = "ecff6bff03b35d482ad5eb51276d6fc4c823cd39" -uuid = "02c8fc9c-b97f-50b9-bbe4-9be30ff0a78a" -version = "2.9.10+2" - -[[Zlib_jll]] -deps = ["Libdl", "Pkg"] -git-tree-sha1 = "fdd89e5ab270ea0f2a0174bd9093e557d06d4bfa" -uuid = "83775a58-1f1d-513f-b197-d71354ab007a" -version = "1.2.11+16" diff --git a/Project.toml b/Project.toml index 60112eb..9757c41 100644 --- a/Project.toml +++ b/Project.toml @@ -1,25 +1,21 @@ name = "SynchronicBallot" uuid = "c4fd2470-c9f5-491f-b4e2-53b9059945a5" authors = ["akels "] -version = "0.3.2" +version = "0.4" [deps] Multiplexers = "d8f48be2-8af9-45f0-b400-11a6372d221d" +PeaceCypher = "7743456c-e0c5-4477-a2b6-196c240b0368" Sockets = "6462fe0b-24de-5631-8697-dd941f90decc" [compat] Multiplexers = "^0.3" +PeaceCypher = "^0.3.3" julia = "1.3" [extras] -DiffieHellman = "0e61fee8-20a4-4374-8233-5198f28d9d66" -CryptoGroups = "bc997328-bedd-407e-bcd3-5758e064a52d" -CryptoSignatures = "35cc5888-0c46-470e-89c7-eafcaf79a1aa" -Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" -Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" -SecureIO = "ee77041e-65ec-469d-b516-892ca52996d6" Sockets = "6462fe0b-24de-5631-8697-dd941f90decc" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["Test", "Sockets", "CryptoGroups", "CryptoSignatures", "SecureIO", "Random", "Pkg", "DiffieHellman"] +test = ["Test", "Sockets"] diff --git a/src/SynchronicBallot.jl b/src/SynchronicBallot.jl index 84a624a..eceadee 100644 --- a/src/SynchronicBallot.jl +++ b/src/SynchronicBallot.jl @@ -1,11 +1,30 @@ module SynchronicBallot -abstract type Layer end -function secure end +using PeaceCypher: CypherSuite, Signer, Secret, Layer, secure, id + +#abstract type Layer end +#function secure end using Multiplexers using Sockets +struct Regulation + N::UInt8 + M::UInt8 + metadata::Vector{UInt8} +end + +struct Ballot + metadata::Vector{UInt8} + votes::Array{UInt8,2} +end + +abstract type Officer end + +function regulation end +function audit! end + + ##### For Debugging ##### import Base.sync_varname @@ -56,7 +75,20 @@ end ####### BallotBox ####### -function mixer(secureserversocket::IO,ballotmember::Layer) +struct Mix + port + id + crypto::CypherSuite +end + +function Sockets.connect(mix::Mix) + layer = Layer(mix.crypto, mix.id) + mixsocket = connect(mix.port) + mixsl = secure(mixsocket, layer) + return mixsl +end + +function serve(secureserversocket::IO, ballotmember::Layer) N = read(secureserversocket,UInt8) M = read(secureserversocket,UInt8) @@ -85,56 +117,43 @@ function mixer(secureserversocket::IO,ballotmember::Layer) ### I need to sort whoole collumns #sort!(shapedmessages, dims=2) # We may need to look into it sortedmessages = sortslices(shapedmessages, dims=2) - stack(secureserversocket,reshape(sortedmessages,:)) + stack(secureserversocket, reshape(sortedmessages,:)) end -struct Mixer - server - daemon -end -function Mixer(port,ballotgate::Layer,ballotmember::Layer) - server = listen(port) +function serve(mix::Mix, signer::Union{Signer, Secret}) + @assert mix.id == id(signer) + layer = Layer(mix.crypto, signer) - daemon = @async while true - gksecuresocket = secure(accept(server),ballotgate) + server = listen(mix.port) - @async while isopen(gksecuresocket) - mixer(gksecuresocket,ballotmember) + while true + client = secure(accept(server), layer) + + @async while isopen(client) + serve(client, layer) end end - - return Mixer(server,daemon) end -function stop(ballotbox::Mixer) - server = ballotbox.server - Sockets.close(server) - @async Base.throwto(ballotbox.daemon,InterruptException()) - return nothing + +struct GateKeeper + port + id + crypto::CypherSuite + mix::Mix end -######## GateKeeper ########### +function run(b::Regulation, usersockets::Vector{IO}, secureroutersocket::IO) + N, M, metadata = b.N, b.M, b.metadata -function gatekeeper(server,secureroutersocket::IO,N::UInt8,M::UInt8,gatemember::Layer,metadata::Vector{UInt8}) - - #serialize(secureroutersocket,N) write(secureroutersocket,UInt8[N,M]) - usersockets = IO[] - - while length(usersockets)wrapsigned(value,key),unwrapmsg,G,chash,() -> rngint(100)) -DHasym() = DH(wrapmsg,unwrapsigned,G,chash,() -> rngint(100)) - -DHsym(key) = DH(value->wrapsigned(value,key),unwrapsigned,G,chash,() -> rngint(100)) - -mixermember = SocketConfig(nothing,DHasym(mixerkey),(socket,key)->SecureSocket(socket,key)) -membermixer = SocketConfig(ballotid,DHasym(),(socket,key)->SecureSocket(socket,key)) - - - -userids = Set() - -user1key = Signer(G) -user2key = Signer(G) -user3key = Signer(G) - -push!(userids,id(user1key)) -push!(userids,id(user2key)) -push!(userids,id(user3key)) - -membergate(memberkey) = SocketConfig(gateid,DHsym(memberkey),(socket,key)->SecureSocket(socket,key)) -gatemember = SocketConfig(userids,DHsym(gatekey),(socket,key)->SecureSocket(socket,key)) - -@sync begin - @async begin - routers = listen(2001) - serversocket = accept(routers) - try - mixer(serversocket,mixermember) - finally - close(routers) - end - end - @async begin - server = listen(2000) - ballotsocket = connect(2001) - try - metadata = Vector{UInt8}("Hello World!") - ballot,signatures = gatekeeper(server,ballotsocket,UInt8(3),UInt8(4),gatemember,metadata) - - for s in signatures - dsasignature = DSASignature{BigInt}(s) - @show verify(dsasignature,G) - @show dsasignature.hash == hash("$metadata $ballot") - end - finally - close(server) - end - end - - @async vote(2000,membergate(user1key),membermixer,Vector{UInt8}("msg1"),(m,b) -> sign(m,b,user1key)) - @async vote(2000,membergate(user2key),membermixer,Vector{UInt8}("msg2"),(m,b) -> sign(m,b,user2key)) - @async vote(2000,membergate(user3key),membermixer,Vector{UInt8}("msg3"),(m,b) -> sign(m,b,user3key)) -end diff --git a/test/daemons.jl b/test/daemons.jl deleted file mode 100644 index 44aef5e..0000000 --- a/test/daemons.jl +++ /dev/null @@ -1,55 +0,0 @@ -### For simplicity we assume the same group to be ussed everywhere. -G = CryptoGroups.Scep256k1Group() # a bug. probably from binary going to value -#G = CryptoGroups.MODP160Group() - -DHasym(key) = DH(value->wrapsigned(value,key),unwrapmsg,G,chash,() -> rngint(100)) -DHasym() = DH(wrapmsg,unwrapsigned,G,chash,() -> rngint(100)) - -DHsym(key) = DH(value->wrapsigned(value,key),unwrapsigned,G,chash,() -> rngint(100)) - -mixerkey = Signer(G) -mixerid = id(mixerkey) - -gatekey = Signer(G) -gateid = id(gatekey) - -userids = Set() - -user1key = Signer(G) -user2key = Signer(G) -user3key = Signer(G) - -push!(userids,id(user1key)) -push!(userids,id(user2key)) -push!(userids,id(user3key)) - -mixermember = SocketConfig(nothing,DHasym(mixerkey),(socket,key)->SecureSocket(socket,key)) -membermixer = SocketConfig(mixerid,DHasym(),(socket,key)->SecureSocket(socket,key)) - -mixergate = SocketConfig(gateid,DHsym(mixerkey),(socket,key)->SecureSocket(socket,key)) -gatemixer = SocketConfig(mixerid,DHsym(gatekey),(socket,key)->SecureSocket(socket,key)) - -membergate(memberkey) = SocketConfig(gateid,DHsym(memberkey),(socket,key)->SecureSocket(socket,key)) -gatemember = SocketConfig(userids,DHsym(gatekey),(socket,key)->SecureSocket(socket,key)) - -### The ballotbox server does: -mixerserver = Mixer(2001,mixergate,mixermember) - -### The gatekeeper does -gkserver = GateKeeper(2000,2001,UInt8(3),UInt8(4),gatemixer,gatemember,()->Vector{UInt8}("Hello World")) - -### Users do: - -@async vote(2000,membergate(user1key),membermixer,Vector{UInt8}("msg1"),(m,b) -> sign(m,b,user1key)) -@async vote(2000,membergate(user2key),membermixer,Vector{UInt8}("msg3"),(m,b) -> sign(m,b,user2key)) -@async vote(2000,membergate(user3key),membermixer,Vector{UInt8}("msg2"),(m,b) -> sign(m,b,user3key)) - -### After that gatekeeper gets ballot - -@show take!(gkserver.ballots) - -### Stopping stuff -sleep(1) - -stop(mixerserver) -stop(gkserver) diff --git a/test/runtests.jl b/test/runtests.jl index cc2b0f5..03b5949 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,102 +1,67 @@ using SynchronicBallot -using CryptoGroups -using CryptoSignatures -using DiffieHellman -using Sockets -using SecureIO -using Pkg.TOML - -# import Serialization -# import SecureIO.SecureSocket -# SecureSocket(socket::TCPSocket,key) = SecureSocket(Socket(socket,Serialization.serialize,Serialization.deserialize),key) - -import Base.Dict -hash(x::AbstractString) = BigInt(Base.hash(x)) - -function chash(envelope1::Vector{UInt8},envelope2::Vector{UInt8},key::BigInt) - str = "$(String(copy(envelope1))) $(String(copy(envelope2))) $key" - inthash = hash(str) - strhash = string(inthash,base=16) - return Vector{UInt8}(strhash) +import PeaceCypher: sign +using PeaceCypher + +struct BallotOfficer <: Officer + members + ballots end -id(s) = hash("$(s.pubkey)") +BallotOfficer() = BallotOfficer([], []) -function wrapsigned(value::BigInt,signer::Signer) - signature = DSASignature(hash("$value"),signer) - signaturedict = Dict(signature) - dict = Dict("value"=>string(value,base=16),"signature"=>signaturedict) - io = IOBuffer() - TOML.print(io,dict) - return take!(io) -end +SynchronicBallot.regulation(bo::BallotOfficer) = Regulation(UInt8(3), UInt8(4), Vector{UInt8}("Hello World")) -function unwrapsigned(envelope::Vector{UInt8}) - dict = TOML.parse(String(copy(envelope))) - value = parse(BigInt,dict["value"],base=16) - signature = DSASignature{BigInt}(dict["signature"]) - @assert verify(signature,G) && signature.hash==hash("$value") - return value, id(signature) -end +SynchronicBallot.audit!(bo::BallotOfficer, ballot::Ballot, signatures) = push!(bo.ballots, (ballot, signatures)) -wrapmsg(value::BigInt) = Vector{UInt8}(string(value,base=16)) -unwrapmsg(envelope::Vector{UInt8}) = parse(BigInt,String(copy(envelope)),base=16), nothing +Base.in(id, bo::BallotOfficer) = id in bo.members -function rngint(len::Integer) - max_n = ( BigInt(1) << len ) - 1 - if len > 2 - min_n = BigInt(1) << (len - 1) - return rand(min_n:max_n) - end - return rand(1:max_n) -end +#### Now some stuff as usual -Signature(data,signer) = DSASignature(hash("$data"),signer) +notary = Notary() +crypto = CypherSuite(notary) -### The sign function ofcourse also depends on the message -function sign(metadata::Vector{UInt8},ballot::Array{UInt8,2},signer::Signer) - h = hash("$metadata $ballot") - signature = DSASignature(h,signer) - sdict = Dict(signature) - io = IOBuffer() - TOML.print(io,sdict) - return take!(io) -end +mixkey = newsigner(notary) +mixid = id(mixkey) -import CryptoSignatures.DSASignature +mix = Mix(3000, mixid, crypto) -function DSASignature{BigInt}(bytes::Vector{UInt8}) - sdict = TOML.parse(String(copy(bytes))) - return DSASignature{BigInt}(sdict) -end +mixtask = @async SynchronicBallot.serve(mix, mixkey) +sleep(1.) -struct SocketConfig <: Layer - id ### Theese list approved ids - dh::DH - SecureSocket -end +### Now the gatekeeper -function _secure(socket::IO, sc::SocketConfig) - key,id = diffiehellman(socket,sc.dh) - @assert id in sc.id "$id not in $(sc.id)" +gatekey = newsigner(notary) +gateid = id(gatekey) - sroutersocket = sc.SecureSocket(socket,key) - return sroutersocket -end -import Base.LibuvStream +gk = GateKeeper(3001, gateid, crypto, mix) -SynchronicBallot.secure(socket::LibuvStream,sc::SocketConfig) = _secure(socket,sc) -SynchronicBallot.secure(socket::IO,sc::SocketConfig) = _secure(socket,sc) +bo = BallotOfficer() +gktask = @async SynchronicBallot.serve!(gk, bo, gatekey) -import Base.in -in(x::Nothing,y::Nothing) = true +sleep(1.) +### Now I need to make users +user1key = newsigner(notary) +user2key = newsigner(notary) +user3key = newsigner(notary) -# The essentials of the protocol -include("core.jl") -# Some higher order configuration -include("daemons.jl") +push!(bo.members, id(user1key)) +push!(bo.members, id(user2key)) +push!(bo.members, id(user3key)) + + +@show istaskstarted(gktask) + +@sync begin + + @async vote(Vector{UInt8}("msg1"), gk, user1key, (m,b) -> binary(sign((m,b), user1key))) + @async vote(Vector{UInt8}("msg2"), gk, user2key, (m,b) -> binary(sign((m,b), user2key))) + @async vote(Vector{UInt8}("msg3"), gk, user3key, (m,b) -> binary(sign((m,b), user3key))) + +end + +@show bo.ballots