Giter Site home page Giter Site logo

encryptogroup / aby Goto Github PK

View Code? Open in Web Editor NEW
444.0 29.0 132.0 11.3 MB

ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation

License: GNU Lesser General Public License v3.0

C++ 96.91% C 2.20% Shell 0.03% CMake 0.86%
secure-computation mpc garbled-circuits secret-sharing circuit encrypto

aby's Introduction

A Framework for Efficient Mixed-Protocol Secure Two-Party Computation

By Daniel Demmler, Thomas Schneider and Michael Zohner (ENCRYPTO, TU Darmstadt)
in Network and Distributed System Security Symposium (NDSS'15). Paper available here.

Table of Contents

Features


ABY efficiently combines secure computation schemes based on Arithmetic sharing, Boolean sharing, and Yao’s garbled circuits and makes available best-practice solutions in secure two-party computation. It allows to pre-compute almost all cryptographic operations and provides novel, highly efficient conversions between secure computation schemes based on pre-computed oblivious transfer extensions using our OT extension library available on GitHub. ABY supports several standard operations and provides example applications.

This code is provided as a experimental implementation for testing purposes and should not be used in a productive environment. We cannot guarantee security and correctness.

Requirements


  • A Linux distribution of your choice (ABY was developed and tested with recent versions of Debian and Ubuntu).

  • Required packages for ABY:

    Install these packages with your favorite package manager, e.g, sudo apt-get install <package-name>.

  • Optional packages: doxygen and graphviz to create your own Doxygen documentation of the code.

ABY Source Code


Repository Structure

  • bin/circ/ - Circuits in the ABY format.
  • cmake/ - CMake helper files.
  • extern/ - External dependencies as Git submodules.
  • src/ - Source code.
  • src/abycore/ - Source of the internal ABY functions.
  • src/examples/ - Example applications. Each application has a /common directory that holds the functionality (circuit). The idea is to re-use this circuit even outside of the application. The application's root directory contains a .cpp file with a main method that runs the circuit and is used to verify correctness.
  • src/test/ - Currently one application to test internal ABY functions as well as example applications and print debug information.

Building the ABY Framework

Short Version
  1. Clone the ABY git repository by running:

    git clone https://github.com/encryptogroup/ABY.git
    
  2. Enter the Framework directory: cd ABY/

  3. Create and enter the build directory: mkdir build && cd build

  4. Use CMake configure the build:

    cmake ..
    

    This also initializes and updates the Git submodules of the dependencies located in extern/. If you plan to work without a network connection, you should to a --recursive clone in Step 1.

  5. Call make in the build directory. You can find the build executables and libraries in the directories bin/ and lib/, respectively.

Detailed Guide
External Dependencies

ABY depends on the OTExtension and ENCRYPTO_utils libraries, which are referenced using the Git submodules in the extern/ directory. During configure phase of the build (calling cmake ..) CMake searches your system for these libraries.

  • If they are already installed at a standard location, e.g., at /usr or /usr/local, CMake should find these automatically.
  • In case they are installed at a nonstandard location, e.g., at ~/some/path/, you can point CMake to their location via the CMAKE_PREFIX_PATH option:
    cmake .. -DCMAKE_PREFIX_PATH=~/some/path/
    
  • Otherwise, CMake updates and initializes the Git submodules in extern/ (if not already done), and the missing dependencies are built together with ABY. If you want to do this without a network connection, consider to clone the repository recursively.
Test Executables and Example Applications

To build the ABY test and benchmark executables as well as the bundled example applications, you use the ABY_BUILD_EXE option:

cmake .. -DABY_BUILD_EXE=On
Build Options

You can choose the build type, e.g. Release or Debug using CMAKE_BUILD_TYPE:

cmake .. -DCMAKE_BUILD_TYPE=Release
# or
cmake .. -DCMAKE_BUILD_TYPE=Debug

Release will enable optimizations whereas Debug includes debug symbols.

To choose a different compiler, use the CXX environment variable:

CXX=/usr/bin/clang++ cmake ..
Cleaning the Build Directory

Executing make clean in the build directory removes all build artifacts. This includes built dependencies and examples. To clean only parts of the build, either invoke make clean in the specific subdirectory or use make -C:

  • make clean - clean everything
  • make -C src/abycore clean - clean only the ABY library
  • make -C src/examples clean - clean only the examples
  • make -C src/test clean - clean only the test application
  • make -C extern clean - clean only the built dependencies
Installation

In case you plan to use ABY for your own application, you might want to install the ABY library to some place, for example system-wide (e.g. at /usr/local) or somewhere in your workspace (e.g. /path/to/aby). There are two relevant options:

  • CMAKE_INSTALL_PREFIX defaults to /usr/local and is preprended by CMake to all installation paths (e.g. lib/ and include/ for library and header files, respectively, become /usr/local/lib and usr/local/include). CMake will also look for dependencies at this location.
  • DESTDIR is used by the Makefile to install to a nonstandard location.

Example: If you want to install ABY to ~/path/to/aby/prefix/{include,lib} you can use:

cmake .. -DCMAKE_INSTALL_PREFIX=""
make
make DESTDIR=~/path/to/aby/prefix install

or

cmake .. -DCMAKE_INSTALL_PREFIX=~/path/to/aby/prefix
make
make install

Developer Guide and Documentation

We provide an extensive developer guide with many examples and explanations of how to use ABY.

Also, see the online doxygen documentation of ABY for further information and comments on the code.

ABY Applications


Included Example Applications

  • The Millionaire's Problem was proposed by Yao in 1982. Two parties want to find out who is richer, without revealing their actual wealth. This simple example can be used as starting point for your own ABY application.
  • Secure computation AES, where one party inputs the key and the other party inputs a message to collaboratively encrypt.
  • The Euclidean Distance for two 2-dimensional coordinates.
  • The Minimum Euclidean Distance for finding the closest match between one d-dimensional element and a database of n d-dimensional elements.
  • The Arithmetic Inner Product that multiplies N values component-wise and then adds all multiplication results (modulo 16 Bit in this case).
  • Secure Hash Function Evaluation SHA1, where both parties concatenate their 256-bit inputs to a 512-bit message which is collaboratively hashed using SHA1.
  • The LowMC block cipher family LowMC, which is a block cipher family with a low number of AND gates and a low AND depth. In the example, one party inputs the key and the other party inputs a message to collaboratively encrypt.
  • Further example applications will be added soon.

Running Applications

  • Make sure you have build ABY as described above and set the -DABY_BUILD_EXE=On option and the application's binary was created in bin/ inside the build directory.
  • To locally execute an application, run the created executable from two different terminals and pass all required parameters accordingly.
  • By default applications are tested locally (via sockets on localhost). You can run them on two different machines by specifying IP addresses and ports as parameters.
  • Example: The Millionaire's problem requires to specify the role of the executing party. All other parameters will use default values if they are not set. You execute it locally with: ./millionaire_prob_test -r 0 and ./millionaire_prob_test -r 1, each in a separate terminal.
  • You should get some debug output for you to verify the correctness of the computation.
  • Performance statistics can be turned on setting #define PRINT_PERFORMANCE_STATS 1 in src/abycore/ABY_utils/ABYconstants.h in line 33.

Creating and Building your own ABY Application

  • To get an idea how to create a simple ABY application, you can follow the comments in the Millionaire's Problem example.

  • If you are using CMake, install ABY somewhere it can be found and use find_package(ABY) or add the ABY repository as subdirectory via add_subdirectory(path/to/ABY), e.g.

     find_package(ABY QUIET)
     if(ABY_FOUND)
     	message(STATUS "Found ABY")
     elseif (NOT ABY_FOUND AND NOT TARGET ABY::aby)
     	message("ABY was not found: add ABY subdirectory")
     	add_subdirectory(extern/ABY)
     endif()

    Then define your executable and link it to the ABY::aby target:

     add_executable(my_application my_application.cpp)
     target_link_libraries(my_application ABY::aby)
  • Otherwise, setup the include path such that the headers of ABY and its dependencies can be found and link your application to the libaby.a library and the other dependencies (see above).

aby's People

Contributors

dd23 avatar fboemer avatar hamidzr avatar ishaq avatar lenerd avatar michaelzohner avatar naderpour avatar oleksandr-tkachenko avatar prankurgit avatar schoppmp avatar sebastianst avatar tkussel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aby's Issues

Lack of Randomness

During our work with ABY I noticed that the generated keys for the Yao sharing are deterministic. If the sharing algorithm is run two times the same keys are used.

This undermines the security of the entire protocol since Yao's garbled circuit must not be reused. An attacker can generate all server-keys and learn the secret server input.

Raspberry pi error

Hi. I'm trying to compile this library under a raspberry pi 3 with ubuntu core, however, I got:

unrecognized command line option '-m32'

This may be because the processor is "ARM". Is there a way to compile this for these types of systems?

parent->context == S_YAO || S_YAO_REV

Hi,

in src/abycore/sharing/yaoclientsharing.cpp:440 it says else if(parent->context == S_YAO || S_YAO_REV) but it should probably be else if(parent->context == S_YAO || parent->context == S_YAO_REV).

Best,
David

Possible problems with operator precedence

There are a few comparisons in combination with bitwise operators. Since these operators have lower precedence than the e.g. ==, the code may not do what was indended by the author

I suggest to place parentheses even if the expression is evaluated as intended.

The line numbers are a bit off, but I linked to the correct lines in this repository.


here

src/abycore/sharing/yaoserversharing.cpp:827:53: warning: ^ has lower precedence than ==; == will be evaluated first [-Wparentheses]
                                        if (m_vClientROTRcvBuf.GetBitNoMask(linbitctr) ^ permval == 1) {
                                                                                       ^~~~~~~~~~~~~~
src/abycore/sharing/yaoserversharing.cpp:827:53: note: place parentheses around the '==' expression to silence this warning
                                        if (m_vClientROTRcvBuf.GetBitNoMask(linbitctr) ^ permval == 1) {
                                                                                       ^
                                                                                         (           )
src/abycore/sharing/yaoserversharing.cpp:827:53: note: place parentheses around the ^ expression to evaluate it first
                                        if (m_vClientROTRcvBuf.GetBitNoMask(linbitctr) ^ permval == 1) {
                                                                                       ^
                                            (                                                   )

here

src/abycore/util/cbitvector.cpp:198:47: warning: operator '<<' has lower precedence than '-'; '-' will be evaluated first [-Wshift-op-parentheses]
                        p[i] = ((m_pBits[posctr] & (((1 << remlen) - 1 << lowermask))) >> lowermask) & 0xFF;
                                                     ~~~~~~~~~~~~~~^~~ ~~
src/abycore/util/cbitvector.cpp:198:47: note: place parentheses around the '-' expression to silence this warning
                        p[i] = ((m_pBits[posctr] & (((1 << remlen) - 1 << lowermask))) >> lowermask) & 0xFF;
                                                                   ^
                                                     (                )

here

src/examples/psi_phasing/common/phasing_circuit.cpp:287:9: warning: & has lower precedence than >; > will be
evaluated first [-Wparentheses]
                        if(j & 0x01 > 0) { //value is odd, hence store highest value on stash
                             ^~~~~~~~~~
src/examples/psi_phasing/common/phasing_circuit.cpp:287:9: note: place parentheses around the '>' expression to silence this warning
                        if(j & 0x01 > 0) { //value is odd, hence store highest value on stash
                             ^
                               (       )
src/examples/psi_phasing/common/phasing_circuit.cpp:287:9: note: place parentheses around the & expression to evaluate it first
                        if(j & 0x01 > 0) { //value is odd, hence store highest value on stash
                             ^
                           (       )

here

src/test/abytest.cpp:177:17: warning: ^ has lower precedence than ==; == will be evaluated first [-Wparentheses]
                                verify = sa ^ sb == 0 ? b : a;
                                            ^~~~~~~~~
src/test/abytest.cpp:177:17: note: place parentheses around the '==' expression to silence this warning
                                verify = sa ^ sb == 0 ? b : a;
                                            ^
                                              (      )
abytest.cpp:177:17: note: place parentheses around the ^ expression to evaluate it first
                                verify = sa ^ sb == 0 ? b : a;
                                            ^
                                         (      )

BooleanCircuit: Templates declared in header, defined in implementation

Various methods of Booleancircuit (e.g. PutINGate) are declared as templates in booleancircuits.h. The corresponding template definition is located in booleancircuits.cpp and, thus, not visible for uses of the class. This results in linker errors if a method is used but not instantiated for a particular template parameter.

"make runtest" fails for A2Y Gate

If we turn on the debug options in makefile, make runtest fails.

We changed the following code (from line 13 - 15 in Makefile ) from

ABY_COMPILER_OPTIONS=-O2 -std=c++14 -march=native
#DEBUG
#ABY_COMPILER_OPTIONS=-g3 -ggdb -O0 -std=c++14 #-fno-omit-frame-pointer -fsanitize=address #-Wall -Wextra -pedantic

to

#ABY_COMPILER_OPTIONS=-O2 -std=c++14 -march=native
#DEBUG
ABY_COMPILER_OPTIONS=-g3 -ggdb -O0 -std=c++14 -fno-omit-frame-pointer -fsanitize=address -Wall -Wextra -pedantic

Error:

Running test no. 24 on operation a2y
Running test no. 24 on operation a2y
=================================================================
==12774==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6020001da310 at pc 0x000000588c12 bp 0x7fffd625d890 sp 0x7fffd625d880
READ of size 8 at 0x6020001da310 thread T0
=================================================================
==12775==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000152eb0 at pc 0x00000057c828 bp 0x7ffff3c51570 sp 0x7ffff3c51560
READ of size 8 at 0x602000152eb0 thread T0
.....
.....

SUMMARY: AddressSanitizer: heap-buffer-overflow ../../abycore/sharing/yaoclientsharing.cpp:427 YaoClientSharing::EvaluateConversionGate(unsigned int)
SUMMARY: AddressSanitizer: heap-buffer-overflow ../../abycore/sharing/yaoserversharing.cpp:275 YaoServerSharing::SendConversionValues(unsigned int)
Shadow bytes around the buggy address:
.....
.....

Attaching complete error information:
makeruntesterrors.txt

Error when running abyfloat_test.exe

When I try to run abyfloat_test.exe from two terminals, I got an error.

~/ABY/build/bin$ ./abyfloat_test -r 0 -x 1.0 -y 2.1
double input values: 1.000 ; 2.100
Error: Unable to open circuit file circ/fp_nostatus_add_64.aby
Complexities: 
Boolean Sharing: ANDs: 0 (1-bit) ; Depth: 1
Total Vec AND: 0
Total Non-Vec AND: 0
XOR vals: 0 gates: 0
Comb gates: 0, CombStruct gates: 0, Perm gates: 0, Subset gates: 0, Split gates: 0
Yao: ANDs: 0 ; Depth: 0
Reverse Yao: ANDs: 0 ; Depth: 0
Arithmetic Sharing: MULs: 0 ; Depth: 0
SP-LUT Sharing: OT-gates: Total OT gates = 0; Depth: 1
Total number of gates: 128 Total depth: 1
Timings: 
Total =		0.493 ms
Init =		0.131 ms
CircuitGen =	0.033 ms
Network =	9498.035 ms
BaseOTs =	232.259 ms
Setup =		0.178 ms
OTExtension =	0.150 ms
Garbling =	0.000 ms
Online =	0.315 ms

Segmentation fault (core dumped)

There is an error "Error: Unable to open circuit file circ/fp_nostatus_add_64.aby".
When I check the file, there isn't such a file. What is this file?

Heap overflow in get_clear_value()

With help of ASan found a buffer overflow occurring when arithmetic sharing is used (see below). I used test case no. 12 "ioarith". For the type sizes I assume a Linux AMD64 platform.

Let's look at ArithSharing<T>::InstantiateGate:

template<typename T>
void ArithSharing<T>::InstantiateGate(GATE* gate) {
	gate->instantiated = true;
	gate->gs.aval = (UGATE_T*) calloc(sizeof(T), gate->nvals);
}

If ArithSharing<T> is instantiated with an unsigned int (usually 32 bit on AMD64), 4 bytes are allocated. However, UGATE_T is defined as a 64 bit integer and needs 8 bytes.

I think sizeof(UGATE_T) should be used here. ASan is satisfied with that solution, but I might have missed something here.


ENCRYPTO_utils/typedefs.h
49:typedef unsigned long long UINT64_T;
53:typedef UINT64_T UGATE_T;
==2903==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200003a410 at pc 0x5555557c2f4b bp 0x7fffffffd580 sp 0x7fffffffd570
READ of size 8 at 0x60200003a410 thread T0
    #0 0x5555557c2f4a in unsigned int share::get_clear_value<unsigned int>() common/../../../abycore/circuit/share.h:96
    #1 0x5555557ba291 in test_standard_ops(aby_ops_t*, ABYParty*, unsigned int, unsigned int, unsigned int, e_role, bool) /home/lennart/git/ABY/src/test/abytest.cpp:254
    #2 0x5555557b8713 in run_tests(e_role, char*, unsigned short, SECURITYLEVELS, unsigned int, unsigned int, unsigned int, e_mt_gen_alg, int, unsigned int, bool, bool) /home/lennart/git/ABY/src/test/abytest.cpp:124
    #3 0x5555557b7251 in main /home/lennart/git/ABY/src/test/abytest.cpp:45
    #4 0x7ffff51f5f49 in __libc_start_main (/usr/lib/libc.so.6+0x20f49)
    #5 0x5555555d7d19 in _start (/home/lennart/git/ABY/bin/test-aby.exe+0x83d19)

0x60200003a414 is located 0 bytes to the right of 4-byte region [0x60200003a410,0x60200003a414)
allocated by thread T0 here:
    #0 0x7ffff6efdce1 in __interceptor_calloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:70
    #1 0x55555562a124 in ArithSharing<unsigned int>::InstantiateGate(GATE*) (/home/lennart/git/ABY/bin/test-aby.exe+0xd6124)
    #2 0x55555562ebd5 in ArithSharing<unsigned int>::AssignOutputShares() (/home/lennart/git/ABY/bin/test-aby.exe+0xdabd5)
    #3 0x555555629cbe in ArithSharing<unsigned int>::FinishCircuitLayer(unsigned int) (/home/lennart/git/ABY/bin/test-aby.exe+0xd5cbe)
    #4 0x55555576a1d3 in ABYParty::EvaluateCircuit() ../../abycore/aby/abyparty.cpp:386
    #5 0x5555557683be in ABYParty::ExecCircuit() ../../abycore/aby/abyparty.cpp:248
    #6 0x5555557ba256 in test_standard_ops(aby_ops_t*, ABYParty*, unsigned int, unsigned int, unsigned int, e_role, bool) /home/lennart/git/ABY/src/test/abytest.cpp:252
    #7 0x5555557b8713 in run_tests(e_role, char*, unsigned short, SECURITYLEVELS, unsigned int, unsigned int, unsigned int, e_mt_gen_alg, int, unsigned int, bool, bool) /home/lennart/git/ABY/src/test/abytest.cpp:124
    #8 0x5555557b7251 in main /home/lennart/git/ABY/src/test/abytest.cpp:45
    #9 0x7ffff51f5f49 in __libc_start_main (/usr/lib/libc.so.6+0x20f49)

SUMMARY: AddressSanitizer: heap-buffer-overflow common/../../../abycore/circuit/share.h:96 in unsigned int share::get_clear_value<unsigned int>()

Random values returned by Y2A gate

To reproduce the problem, I am attaching a small program. It checks the condition (x > 0), in a loop for 10 times and the value of x is always 0.

share* put_cons32_gate(Circuit* c, uint32_t val) {
	return c->PutCONSGate((UGATE_T)val, (uint32_t)32);
}
int32_t test_millionaire_prob_circuit(....)
{
        ...
        Circuit* ycirc = (*sharings)[S_YAO]->GetCircuitBuildRoutine();
        Circuit* acirc = (*sharings)[S_ARITH]->GetCircuitBuildRoutine();
        Circuit* bcirc = (*sharings)[S_BOOL]->GetCircuitBuildRoutine();

        share* output[10];
        share* variable = put_cons32_gate(ycirc, 0);
        share* condition = put_cons32_gate(ycirc, 0);
        for (uint32_t i = 0; i < 10; i++){
                condition = acirc->PutY2AGate(ycirc->PutGTGate(variable, put_cons32_gate(ycirc, 0)), bcirc);;
                output[i] = acirc->PutOUTGate(condition, ALL);
        }
        party->ExecCircuit();
        for (uint32_t i = 0; i < 10; i++){
                cout << output[i]->get_clear_value<uint32_t>() << endl; 
        }
       delete party;
}

The result of the operation should be always 0, where as in some iterations it is a random non-zero value.


If we change the inside of for loop by removing the PutY2AGate to as below, it prints only 0's which is the expected output.

       condition = ycirc->PutGTGate(variable, put_cons32_gate(ycirc, 0));;
       output[i] = ycirc->PutOUTGate(condition, ALL);

All shares used are private and each iteration of the loop executes the same code. Extract the millionaire_prob.cpp, copy it to the millionaire_prob.cpp in the repo src/examples/millionaire_prob/common/millionaire_prob.cpp , make and run the millionaire_prob.exe.
This issue might be linked to #46 as Y2A uses B2A .

Attachment:

millionaire_prob.zip


Thanks.

Error when building ABY framework

When I tried to build the ABY framework, these errors occurred.

ABY/src/abycore/sharing/boolsharing.cpp:20:22: fatal error: filesystem: No such file or directory
compilation terminated.
src/abycore/CMakeFiles/aby.dir/build.make:192: recipe for target 'src/abycore/CMakeFiles/aby.dir/sharing/boolsharing.cpp.o' failed
make[2]: *** [src/abycore/CMakeFiles/aby.dir/sharing/boolsharing.cpp.o] Error 1
CMakeFiles/Makefile2:260: recipe for target 'src/abycore/CMakeFiles/aby.dir/all' failed
make[1]: *** [src/abycore/CMakeFiles/aby.dir/all] Error 2
Makefile:129: recipe for target 'all' failed
make: *** [all] Error 2

Then I tried to change filesystem into experimental/filesystem , but it didn't work.

B2AGate() returns weird values

I am trying a code that performs both Boolean and Arithmetic operations on SIMD values.
The first call on the B2AGate() function works fine, but a second call to the same B2AGate generates weird and random-looking numbers. Can the B2AGate function be only called once in a circuit?

I believe my problem is the same as this issue opened last year:
#24

Thank you.

Socket recv error

Hi, I was testing party->reset( ) functionality and it seems that whenever that function is invoked, one of the terminals that runs the program is killed and the other terminal outputs "socket recv: unexpected shutdown by peer".

The code I was testing included:

1. Loop thru some iterations:
    2. create a Circuit * ptr for a boolean circuit. 
    3. Put in values (via PutINGate)
    4. Put in operations (sub/mul) on create share objects
    5. party->ExecCircuit()
    6. extract values (via PutOUTGate)
    7. party->Reset()

Similar behavior is seen when I tested the example program "./bench_operations.exe".

Are there system/environment preference that needs to be modified in order to avoid the sockets from closing unexpectedly?

Build issues in Mac OS X

I ran the cmake .. command successfully.
On running the make command, I saw the following error messages:

[ 52%] Built target miracl
[ 53%] Building CXX object extern/ENCRYPTO_utils/CMakeFiles/encrypto_utils.dir/src/ENCRYPTO_utils/channel.cpp.o
In file included from /Users/deevashwer/ABY/extern/ENCRYPTO_utils/src/ENCRYPTO_utils/channel.cpp:3:
/Users/deevashwer/ABY/extern/ENCRYPTO_utils/src/ENCRYPTO_utils/typedefs.h:71:16: warning: left side of operator converted from negative value to unsigned: -1 to 18446744073709551615
#elif (MAX_INT == 0xFFFFFFFFFFFFFFFF)
       ~~~~~~~ ^  ~~~~~~~~~~~~~~~~~~
In file included from /Users/deevashwer/ABY/extern/ENCRYPTO_utils/src/ENCRYPTO_utils/channel.cpp:4:
/Users/deevashwer/ABY/extern/ENCRYPTO_utils/src/ENCRYPTO_utils/rcvthread.h:58:46: error: implicit instantiation of undefined template 'std::__1::array<RcvThread::rcv_task, 256>'
        std::array<rcv_task, MAX_NUM_COMM_CHANNELS> listeners;
                                                    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/__tuple:223:64: note: template is declared here
template <class _Tp, size_t _Size> struct _LIBCPP_TEMPLATE_VIS array;
                                                               ^
1 warning and 1 error generated.
make[2]: *** [extern/ENCRYPTO_utils/CMakeFiles/encrypto_utils.dir/src/ENCRYPTO_utils/channel.cpp.o] Error 1
make[1]: *** [extern/ENCRYPTO_utils/CMakeFiles/encrypto_utils.dir/all] Error 2
make: *** [all] Error 2

Can someone suggest any changes to Makefile that will resolve this issue?

PSI Examples won't compile

I have a problem compiling the examples.
In psi_phasing.cpp the compiler complains:

common/phasing_circuit.o: In function `BooleanCircuit::PutINGate(unsigned int, unsigned int, unsigned int, e_role)':
phasing_circuit.cpp:(.text._ZN14BooleanCircuit9PutINGateEjjj6e_role[_ZN14BooleanCircuit9PutINGateEjjj6e_role]+0x1): undefined reference to `share* BooleanCircuit::InternalPutINGate<unsigned int>(unsigned int, unsigned int, unsigned int, e_role)'

A similar error occurs for the psi_scs example, all others compile just fine.
Any help is greatly appreciated!

Memory Management

Hi, I am new to ABY, but I found many "new" in ABY, such as in share = PUTXXGate(share).
So I am curious that does the ABY do the memory management for us ? Or we should pay attention about the memory leakage ?

Comparison of unsigned expressions with 0

src/abycore/util/socket.h:240:12: warning: comparison of unsigned expression < 0 is always false [-Wtautological-compare]
                        if (ret < 0) {
                            ~~~ ^ ~ 

This is in the method uint64_t Receive(void* pBuf, uint64_t nLen, int nFlags = 0).

The variable ret is declared as unsigned. It used to store the return value of recv.

uint64_t ret = 0;
[...]
ret = recv(m_hSock, p, n, 0);

recv returns a signed value (ssize_t in POSIX, int in Winsock), where a negative value represents an error.

Since it is assigned to an unsigned variable, the error handling will never be executed:

        if (ret < 0) {
            if ( errno == EAGAIN) {
                cerr << "socket recv eror: EAGAIN" << endl;
                SleepMiliSec(200);
                continue;
            } else {
                cerr << "socket recv error: " << errno << endl;
                perror("Socket error "); 
                return ret;
            }   
        } else if (ret == 0) {

If an error occurs, the negative return value will be converted to a large positive number. That will probably result in undesired behavior.

src/abycore/util/crypto/crypto.cpp:447:14: warning: comparison of unsigned express ion < 0 is always false [-Wtautological-compare]
                if (result < 0) {
                    ~~~~~~ ^ ~

The same thing happens here, read returns a ssize_t.

void gen_secure_random(uint8_t* dest, uint32_t nbytes) {
    int32_t randomData = open("/dev/random", O_RDONLY);
    uint32_t bytectr = 0;
    while (bytectr < nbytes) {
        uint32_t result = read(randomData, dest + bytectr, nbytes - bytectr);
        if (result < 0) {
            cerr << "Unable to read from /dev/random, exiting" << endl;
            exit(0);
        }
        bytectr += result;
    }
    close(randomData);
}

src/examples/psi_scs/common/sort_compare_shuffle.cpp:320:35: warning: comparison of unsigned expression >= 0 is always true [-Wtautological-compare]
                        for (k = 0; k < i && j - i - k >= 0; k++) {
                                             ~~~~~~~~~ ^  ~

Here is another issue.

abstract class without virtual destructor

The class Sharing is an abstract base class, but its destructor is not declared virtual.

see C++ FAQ

src/abycore/aby/abyparty.cpp:126:3: warning: delete called on 'Sharing' that is abstract but has non-virtual destructor [-Wdelete-non-virtual-dtor]
                delete m_vSharings[S_BOOL];
                ^
src/abycore/aby/abyparty.cpp:128:3: warning: delete called on 'Sharing' that is abstract but has non-virtual destructor [-Wdelete-non-virtual-dtor]
                delete m_vSharings[S_YAO];
                ^
src/abycore/aby/abyparty.cpp:130:3: warning: delete called on 'Sharing' that is abstract but has non-virtual destructor [-Wdelete-non-virtual-dtor]
                delete m_vSharings[S_YAO_REV];
                ^
src/abycore/aby/abyparty.cpp:132:3: warning: delete called on 'Sharing' that is abstract but has non-virtual destructor [-Wdelete-non-virtual-dtor]
                delete m_vSharings[S_ARITH];

Does ABY support real numbers?

I want to test the performance of addition and multiplication of real numbers in ABY.
Is there built-in types for fixed-point or floating-point numbers in ABY?
Does ABY support right shift or left shift operations for sharings?

Sockets error

I'm trying to run the program of millionaire's problem but if I run "two times" in row, sometimes I get

"Error: a socket could not be bound
Listen failed
There was an error during establish connection, ending!"

or

"(1) connection failed due to timeout!"

Load a share object on a circuit

Hi,

How can I load a share object on a circuit (Assuming the share object is an output of another circuit).
The PutINGate and PutSIMDINGate seem to only accept plaintext values (unsigned int).

Thank you.

PrintValueGate and AssertGate

In the developer guide you mention PutPrintValueGate and PutAssertGate.
Since I cannot seem to find those in the current release, I'm assuming you have a more recent version, which is not yet released?
Are you planning to release those anytime soon?

Thanks for your great work 👍

Can't make the project

make: *** No rule to make target 'src/abycore/util/Miracl/*', needed by 'src/abycore/util/miracl_lib/miracl.a'. Stop.

Authentication

What type of authentication ABY has?

You already implement the Extension to Malicious Adversaries?

Running program between two computers

We tried running the millionaire_prob in two terminals in one virtual machine in the same computer, and it works okay.
Then, we tried running the millionaire_prob between two virtual machines in the same computer, and it works okay.
But, we cannot successfully run the millionaire_prob between two computers (comp 1 and comp 2) connected by LAN.

comp 1 has the following details:
IP Address - 192...001
Port - default

comp 2 has the following details:
IP Address - 192...002
Port - default

If we want to run the millionaires problem on these computers (comp 1 as server, comp 2 as client)
what should be the syntax on both computers?

When we type "./millionaire_prob.exe -r 0 -a 192...001" in a terminal in comp 1 and "./millionaire_prob.exe -r 1 -a 192...001" in a terminal in comp 2, both terminals do not return anything and run indefinitely.

Any help would be appreciated.

psi_phasing crashes when bit length is less than 25

The example psi_phasing.exe crashes when used with bit-lengths that can be represented in less than 4 bytes. For example, calling

bin/psi_phasing.exe -r 0 -n 100 -b 24 & bin/psi_phasing.exe -r 1 -n 100 -b 24

gives the following error:

[1] 6185
psi_phasing.exe: common/phasing_circuit.cpp:187: int32_t test_phasing_circuit(e_role, char*, uint16_t, seclvl, uint32_t, uint32_t, uint32_t, double, uint32_t, e_mt_gen_alg, e_sharing, int, uint32_t, uint32_t): Assertion `circ_inter_ctr == ver_inter_ctr' failed.
32.115	0.98	968.399	2536922
[1]  + 6185 done       bin/psi_phasing.exe -r 0 -n 100 -b 24
[2]    6186 abort (core dumped)  bin/psi_phasing.exe -r 1 -n 100 -b 24

If the argument to the -b flag is set to 25 or higher, it works without any problems.

Compiling with CFLAGS=-g and calling the crashing process with valgrind indicates memory errors in the hashElement and test_phasing_circuit functions:

bin/psi_phasing.exe -r 0 -n 100 -b 24 & valgrind bin/psi_phasing.exe -r 1 -n 100 -b 24 
[1] 19652
==19653== Memcheck, a memory error detector
==19653== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==19653== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==19653== Command: bin/psi_phasing.exe -r 1 -n 100 -b 24
==19653== 
==19653== Warning: set address range perms: large range [0x903a040, 0x1a2e2840) (defined)
==19653== Thread 10:
==19653== Invalid write of size 4
==19653==    at 0x4192E0: hashElement (hashing_util.h:182)
==19653==    by 0x4192E0: insert_element (simple_hashing.cpp:129)
==19653==    by 0x4192E0: gen_entries(void*) (simple_hashing.cpp:119)
==19653==    by 0x52D82E6: start_thread (in /usr/lib/libpthread-2.25.so)
==19653==    by 0x677A54E: clone (in /usr/lib/libc-2.25.so)
==19653==  Address 0x1cebfbc0 is 0 bytes inside a block of size 3 alloc'd
==19653==    at 0x4C2CF35: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19653==    by 0x4191F7: gen_entries(void*) (simple_hashing.cpp:114)
==19653==    by 0x52D82E6: start_thread (in /usr/lib/libpthread-2.25.so)
==19653==    by 0x677A54E: clone (in /usr/lib/libc-2.25.so)
==19653== 
==19653== Invalid write of size 4
==19653==    at 0x419F6D: hashElement (hashing_util.h:182)
==19653==    by 0x419F6D: gen_cuckoo_entry (cuckoo.cpp:189)
==19653==    by 0x419F6D: gen_cuckoo_entries(void*) (cuckoo.cpp:174)
==19653==    by 0x52D82E6: start_thread (in /usr/lib/libpthread-2.25.so)
==19653==    by 0x677A54E: clone (in /usr/lib/libc-2.25.so)
==19653==  Address 0x1d2b0080 is 0 bytes inside a block of size 3 alloc'd
==19653==    at 0x4C2CF35: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19653==    by 0x419ED2: gen_cuckoo_entry (cuckoo.cpp:187)
==19653==    by 0x419ED2: gen_cuckoo_entries(void*) (cuckoo.cpp:174)
==19653==    by 0x52D82E6: start_thread (in /usr/lib/libpthread-2.25.so)
==19653==    by 0x677A54E: clone (in /usr/lib/libc-2.25.so)
==19653== 
==19653== Thread 1:
==19653== Invalid read of size 4
==19653==    at 0x4183DC: test_phasing_circuit(e_role, char*, unsigned short, SECURITYLEVELS, unsigned int, unsigned int, unsigned int, double, unsigned int, e_mt_gen_alg, e_sharing, int, unsigned int, unsigned int) (phasing_circuit.cpp:126)
==19653==    by 0x405AD1: main (psi_phasing.cpp:110)
==19653==  Address 0x1d2e0434 is 0 bytes after a block of size 36 alloc'd
==19653==    at 0x4C2AF1F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19653==    by 0x41A564: cuckoo_hashing(unsigned char*, unsigned int, unsigned int, unsigned int, unsigned int*, unsigned int*, unsigned int*, unsigned int, unsigned char**, unsigned int, unsigned int**, unsigned int, prf_state_ctx*) (cuckoo.cpp:128)
==19653==    by 0x417604: ClientHashingRoutine(unsigned char*, unsigned int, unsigned int, unsigned int, unsigned char**, unsigned int*, unsigned int*, unsigned char**, unsigned int, unsigned int**, unsigned int, crypto*, unsigned int) (phasing_circuit.cpp:364)
==19653==    by 0x418110: test_phasing_circuit(e_role, char*, unsigned short, SECURITYLEVELS, unsigned int, unsigned int, unsigned int, double, unsigned int, e_mt_gen_alg, e_sharing, int, unsigned int, unsigned int) (phasing_circuit.cpp:83)
==19653==    by 0x405AD1: main (psi_phasing.cpp:110)
==19653== 
psi_phasing.exe: common/phasing_circuit.cpp:187: int32_t test_phasing_circuit(e_role, char*, uint16_t, seclvl, uint32_t, uint32_t, uint32_t, double, uint32_t, e_mt_gen_alg, e_sharing, int, uint32_t, uint32_t): Assertion `circ_inter_ctr == ver_inter_ctr' failed.
==19653== 
==19653== Process terminating with default action of signal 6 (SIGABRT): dumping core
==19653==    at 0x66C1A10: raise (in /usr/lib/libc-2.25.so)
==19653==    by 0x66C3139: abort (in /usr/lib/libc-2.25.so)
==19653==    by 0x66BA606: __assert_fail_base (in /usr/lib/libc-2.25.so)
==19653==    by 0x66BA6B1: __assert_fail (in /usr/lib/libc-2.25.so)
==19653==    by 0x418CEC: test_phasing_circuit(e_role, char*, unsigned short, SECURITYLEVELS, unsigned int, unsigned int, unsigned int, double, unsigned int, e_mt_gen_alg, e_sharing, int, unsigned int, unsigned int) (phasing_circuit.cpp:187)
==19653==    by 0x405AD1: main (psi_phasing.cpp:110)
==19653== 
==19653== HEAP SUMMARY:
==19653==     in use at exit: 289,114,248 bytes in 5,558 blocks
==19653==   total heap usage: 44,972 allocs, 39,414 frees, 314,858,330 bytes allocated
==19653== 
==19653== LEAK SUMMARY:
==19653==    definitely lost: 35,264 bytes in 323 blocks
==19653==    indirectly lost: 3,576 bytes in 322 blocks
==19653==      possibly lost: 2,304 bytes in 8 blocks
==19653==    still reachable: 289,073,104 bytes in 4,905 blocks
==19653==         suppressed: 0 bytes in 0 blocks
==19653== Rerun with --leak-check=full to see details of leaked memory
==19653== 
==19653== For counts of detected and suppressed errors, rerun with: -v
==19653== ERROR SUMMARY: 203 errors from 3 contexts (suppressed: 0 from 0)
[2]    19653 abort (core dumped)  valgrind bin/psi_phasing.exe -r 1 -n 100 -b 24

The last error is probably caused by the stash elements being read in 32-bit words, while they are only allocated using the number of bytes actually needed in cuckoo.cpp:128.
Reading and writing hashed elements byte-wise might fix this, however, I haven't managed to find all the places that would need to be changed.

Check return value of malloc/calloc

There are a lot of calls to malloc in this code, but I have seen only one check of its return value.
If the memory allocation fails, malloc and calloc return NULL. Therefore, an unhandled error, e.g. in case of exhausted memory, will most likely result in an out-of-bounds access. The program crashes with a segmentation fault and no error helpful message is provided.

To address this issue, we could use a wrapper like the following and replace the calls to malloc with xmalloc.

void* xmalloc(size_t size)
{
    void* buf = malloc(size);
    if (buf == NULL)
    {
        fprintf(stderr, "Memory allocation failed: exiting\n");
        exit(1);
    }
    return buf;
}

Another option would be using the new operator of C++, which may throw std::bad_alloc, or a std::vector in some cases. Is there any reason, why malloc and new are mixed in the codebase?

Suggested fix so will compile correctly gcc 5.3 c++14 ubuntu 16.04 (currently with error)

I get the following error:

/home/ab/ABY/src/abycore/circuit/booleancircuits.cpp:2139:42: error: cannot call member function ‘uint32_t BooleanCircuit::PutSizeOptimizedGTGate(std::vector, std::vector)’ without object
uint32_t cmp = (m_eContext == S_YAO) ?
^
/home/ab/ABY/src/abycore/circuit/booleancircuits.cpp:2139:42: error: cannot call member function ‘uint32_t BooleanCircuit::PutDepthOptimizedGTGate(std::vector, std::vector)’ without object
/home/ab/ABY/src/abycore/circuit/booleancircuits.cpp:2142:32: error: cannot call member function ‘std::vector BooleanCircuit::PutMUXGate(std::vector, std::vector, uint32_t, BOOL)’ without object
return PutMUXGate(a, b, cmp);
^
/home/ab/ABY/src/abycore/circuit/booleancircuits.cpp: In member function ‘std::vector BooleanCircuit::PutMaxGate(const std::vector<std::vector >&)’:
/home/ab/ABY/src/abycore/circuit/booleancircuits.cpp:2143:4: error: conversion from ‘BooleanCircuit::PutMaxGate(const std::vector<std::vector >&)::<lambda(auto:1, auto:2)>’ to non-scalar type ‘BinaryOp_v_uint32_t {aka std::function<std::vector(const std::vector&, const std::vector&)>}’ requested

to fix this, I added "this->" in line ~2140 in booleancircuits.cpp

BinaryOp_v_uint32_t op = [this](auto a, auto b) {
			uint32_t cmp = (m_eContext == S_YAO) ?
				this->PutSizeOptimizedGTGate(a, b) :
				this->PutDepthOptimizedGTGate(a, b);
			return this->PutMUXGate(a, b, cmp);

How to interpret Benchmark Times

I'm probably being lazy by not checking it in the source code and asking question here but my rationale is that this topic is covered in the developer guide and therefore should be clarified for the end-users/general-public. If I didn't get an answer, I'll dig deeper and post my findings.

My output looks like this (relevant excerpt):

Timings: 
Total =		13.331 ms
Init =		376.002 ms
CircuitGen =	8.516 ms
Network =	7247.1 ms
BaseOTs =	492.589 ms
Setup =		8.102 ms
OTExtension =	2.839 ms
Garbling =	0.643 ms
Online =	5.225 ms

Question is, why is Total time less than Init time? How should we interpret the different times? If it helps, my program is a simple multiplication gate (Alice and Bob input a and b, result is a*b). it has only 4 gates. (two input gates, one multiplication gate and one reconstruction (OUT) gate).

Also, I am executing it in Arithmetic Sharing, so Garbling time doesn't make much sense.

create_new_share declared static

In section 2.2.4 Share Creation of the developer guide the following functions are introduced:

static share* create_new_share(uint32_t size, Circuit* circ);
static share* create_new_share(vector<uint32_t> wireids, Circuit* circ);

They are defined in src/abycore/circuit/circuit.cpp using the static keyword. Therefore the symbols are not exported and the function can only be used in the same translation unit. Using them in another file results in a linking error.

If these functions are meant to be part of the public API, I see no reason to declare them static. Otherwise they should neither be exposed by the headers nor advertised in the documentation.

My guess is someone moved them from class to namespace scope and forgot to remove the static modifier.

PutBarrelRightShifterGate Problem

Hi, I was having problem getting the PutBarrelRightShifterGate work as expected. I set a number share to 110 and shift share to 1 and passed those to the BooleanCircuit PutBarrelRightShifterGate function. The expected result was 11 from the output but the result received was 220.

Both shares were uint8_t. I added a screenshot of the code I am referring to. My question is, is that correct behavior and I am misinterpreting the functionality? Thank you in advance.

image

Responsibility for the deallocation of share objects

Each time a gate is created via the Put...Gate, e.g. BooleanCircuit::PutXORGate(share*, share*), a share object is created.

share* BooleanCircuit::PutXORGate(share* ina, share* inb) {
	return new boolshare(PutXORGate(ina->get_wires(), inb->get_wires()), this);
}

Following the examples and building a circuit like this results in memory leaks.

			s_f = circ->PutANDGate(s_b, s_c);
			s_tmp = circ->PutANDGate(s_b, s_d);
			s_f = circ->PutXORGate(s_f, s_tmp);

The pointer s_f to the object allocated by PutANDGate is overwritten in the third line and the corresponding object remains in memory without being used ever again.

If the user is responsible for the deallocation of the share objects, it should be noted in the developer guide and done in the examples applications.

A different (and in my eyes more pleasant) solution would be something like this:

using share_p = std::shared_ptr<share>;
share_p BooleanCircuit::PutXORGate(share_p ina, share_p inb) {
	return std::make_shared<boolshare>(PutXORGate(ina->get_wires(), inb->get_wires()), this);
}

The created boolshare gets destroyed as soon as all copies of the std::shared_ptr are gone.

CMake files

Has anyone ever made "cmakefiles" for this project?

Incorrect SIMD FP Multiplications in YAO Sharing

When doing SIMD FloatingPoint Multiplications in YAO Sharing, some of the resulting values are incorrect. Here is a small example that reproduces the issue (run e.g. with nvals=3):

int32_t test_float_circuit(e_role role, const std::string &address, uint16_t port, seclvl seclvl,
     uint32_t nvals, uint32_t nthreads, e_mt_gen_alg mt_alg) {

    	double afp, bfp;
	uint64_t *aptr, *bptr;
	uint32_t bitlen = 64; // values are double --> 64 bit.

	ABYParty* party = new ABYParty(role, address, port, seclvl, bitlen, nthreads,
		mt_alg);

	std::vector<Sharing*>& sharings = party->GetSharings();

	BooleanCircuit* yc = (BooleanCircuit*) sharings[S_YAO]->GetCircuitBuildRoutine();

	srand(time(NULL));

	uint64_t avals[nvals];
	uint64_t bvals[nvals];
	double cvals[nvals];

	for (int i = 0; i < nvals; ++i)
	{
		afp = ((float) rand()) / (float) RAND_MAX;
		bfp = ((float) rand()) / (float) RAND_MAX;

		aptr = (uint64_t*) &afp;
		bptr = (uint64_t*) &bfp;

		avals[i] = *aptr;
		bvals[i] = *bptr;
		cvals[i] = afp*bfp;
	}

	share* ain = yc->PutSIMDINGate(nvals, avals, bitlen, SERVER);
	share* bin = yc->PutSIMDINGate(nvals, bvals, bitlen, CLIENT);

	share* c = yc->PutFPGate(ain, bin, MUL, bitlen, nvals, no_status);

	share* res_out = yc->PutOUTGate(c, ALL);

	// run SMPC
	party->ExecCircuit();

	// retrieve plain text output
	uint32_t out_bitlen, out_nvals;
	uint64_t *out_vals;
	res_out->get_clear_value_vec(&out_vals, &out_bitlen, &out_nvals);

	for (uint32_t i = 0; i < nvals; i++) {

		// dereference output value as double without casting the content
		double val = *((double*) &out_vals[i]);

		std::cout << "RES: " << val << " Verification: " << cvals[i] << std::endl;
	}

	return 0;
} 

Example output:

RES: 0.184405 Verification: 0.184405
RES: 0.000746032 Verification: 0.00298413
RES: 0.0246997 Verification: 0.0987986

Sometimes all the results are correct, sometimes one or two results are incorrect. However the first result seems to always be correct? Using the same values for every dimension also works without issues.

Concurrency Issues

This issue tracks concurrency related problems that are currently known.

  • abyparty/-setup: add synchronization to worker job (fixed in #67 )
  • more fixes in encryptogroup/ENCRYPTO_utils#6
  • Check the current state of #16
  • After a channel is destroyed the RcvThread tries to signal its condition variable.
  • There is probably an issues where ABYParty::ThreadSendValues/ThreadReceiveValues access a buffer concurrently with other methods from different sharing schemes.
  • ...

Keep changes to cout flags local

It would be great if ABY kept changes to cout (and possibly other streams) flags local, i.e., save them before changing them and then restore them. An RAII solution that probably should go into ENCRYPTO_utils could be the following class

/**
 * RAII ostream flags saver
 * https://stackoverflow.com/a/18822888/1523730
 */
class ios_flags_saver {
  public:
    explicit ios_flags_saver(std::ostream& _ios):
      ios(_ios),
      f(_ios.flags()) {}
    ~ios_flags_saver() {
      ios.flags(f);
    }

    ios_flags_saver(const ios_flags_saver&) = delete;
    ios_flags_saver& operator=(const ios_flags_saver&) = delete;

  private:
    std::ostream& ios;
    std::ios::fmtflags f;
};

Then one could write

ios_flags_saver _flags_saver(std::cout);

at the beginning of each function that modifies cout.

This would be especially desirable for Sharing::EvaluatePrintValGate, where cout is currently reset to decimal printing with << std::dec which might not have been the state before the function call.

Heap overflow in psi_phasing

Starting psi_phasing with the same parameters as in the test (./psi_phasing.exe -r 1 -n 1024 -b 32) results in a heap overflow.

In simple_hashing.cpp, ctx->hs->outbitlen is 24 resulting in 3 bytes to be allocated.

	tmpbuf = (uint8_t*) calloc(ceil_divide(ctx->hs->outbitlen, 8), sizeof(uint8_t));

The buffer is passed to insert_element and hashElement where it is used as pointer to a uint32_t. Thus, 4 bytes are written.

	*((uint32_t*) val)  = R;

=================================================================
==16970==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200003a030 at pc 0x5555557d65b8 bp 0x7fffdd209d70 sp 0x7fffdd209d60
WRITE of size 4 at 0x60200003a030 thread T9
    #0 0x5555557d65b7 in hashElement(unsigned char*, unsigned int*, unsigned char*, hashing_state_ctx*) common/hashing/hashing_util.h:182
    #1 0x5555557d99f5 in insert_element(simple_hash_table_ctx*, unsigned char*, unsigned int*, unsigned char*, hashing_state_ctx*) common/hashing/simple_hashing.cpp:129
    #2 0x5555557d8bf2 in gen_entries(void*) common/hashing/simple_hashing.cpp:119
    #3 0x7ffff676c08b in start_thread (/usr/lib/libpthread.so.0+0x708b)
    #4 0x7ffff52cae7e in __GI___clone (/usr/lib/libc.so.6+0xf5e7e)

0x60200003a033 is located 0 bytes to the right of 3-byte region [0x60200003a030,0x60200003a033)
allocated by thread T9 here:
    #0 0x7ffff6efdce1 in __interceptor_calloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:70
    #1 0x5555557d8a87 in gen_entries(void*) common/hashing/simple_hashing.cpp:114
    #2 0x7ffff676c08b in start_thread (/usr/lib/libpthread.so.0+0x708b)

Thread T9 created by T0 here:
    #0 0x7ffff6e53511 in __interceptor_pthread_create /build/gcc/src/gcc/libsanitizer/asan/asan_interceptors.cc:243
    #1 0x5555557d83a6 in simple_hashing(unsigned char*, unsigned int, unsigned int, unsigned int*, unsigned int*, unsigned int, unsigned int*, unsigned int, unsigned int, prf_state_ctx*) common/hashing/simple_hashing.cpp:53
    #2 0x5555557ce2ad in ServerHashingRoutine(unsigned char*, unsigned int, unsigned int, unsigned int, unsigned int*, unsigned char**, unsigned int*, unsigned int, crypto*, unsigned int) common/phasing_circuit.cpp:327
    #3 0x5555557cbf85 in test_phasing_circuit(e_role, char*, unsigned short, SECURITYLEVELS, unsigned int, unsigned int, unsigned int, double, unsigned int, e_mt_gen_alg, e_sharing, int, unsigned int, unsigned int) common/phasing_circuit.cpp:71
    #4 0x5555557e2325 in main /home/lennart/git/ABY/src/examples/psi_phasing/psi_phasing.cpp:109
    #5 0x7ffff51f5f49 in __libc_start_main (/usr/lib/libc.so.6+0x20f49)

SUMMARY: AddressSanitizer: heap-buffer-overflow common/hashing/hashing_util.h:182 in hashElement(unsigned char*, unsigned int*, unsigned char*, hashing_state_ctx*)
Shadow bytes around the buggy address:
  0x0c047ffff3b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047ffff3c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047ffff3d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047ffff3e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047ffff3f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c047ffff400: fa fa 00 04 fa fa[03]fa fa fa fa fa fa fa fa fa
  0x0c047ffff410: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047ffff420: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047ffff430: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047ffff440: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047ffff450: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==16970==ABORTING

Accessing elements from SMID gate

How can we access an element in a SMID gate ( Boolean and arithmetic )?
If the answer is using PutSplitterGate and getting the element using a getter methods, then please give me a working example, since it is not working for me...
Thanks...

Variable definitions in the Makefiles

A target to build ABY as a (static) library would be nice, so that one does not have to bother with a list of object files. When I tried to implement such a target, I noticed some weird behavior during the build process.

Assignments of the following type are problematic:
OBJECTS_CORE := $(shell find ${CORE} -type f -name '*.o' -not -path '*/util/miracl_lib/*' -not -path '*/ot/external/*')
If the objects do not exist, the variable will be empty. So one cannot use the variable as dependency in another rule.

A make core (core: miracl otext ${OBJECTS_CORE}) does not do much in a clean repository.

If I understand the Makefiles correctly, the only reason that a simple make (or make all) works, is that it depends on the example applications, which in turn require the object files.
The variable OBJECTS_CORE is defined differently in the two Makefiles and I am not sure why that is the case.

make fails (openssl issues) with Ubuntu 16.04 and libssl-dev 1.0.2g

With the current commit of the public branch, make fails with openssl errors on Ubuntu 16.04.
I checked the travis log of this repo and found that the openssl version that the travis CI uses is 1.0.1f (which is available for 14.04) which is not available for Ubuntu 16.04. The latest version of libssl-dev for Ubuntu 16.04 is 1.0.2g.
This causes the make to crash.
I am attaching the make log on my machine running Ubuntu 16.04 with libssl-dev 1.0.2g. Errors are shown from line 12 to line 30 in the log.
makelog.txt

Missing cleanup of threads

While testing my circuits I saw that with each invocation of ABY a few more threads were added to the process.

I traced the creation and joining of threads in the sha1 example:

  • 10 threads created
  • 6 thread joined

Here are the full call stacks:

./bin/sha1.exe -r 0
======================
calling pthread_create (1)
----------------------
./bin/sha1.exe(CThread::Start() 0xfd)[0x4818dd]
./bin/sha1.exe(ABYSetup::Init() 0x111)[0x4f83a1]
./bin/sha1.exe(ABYSetup::ABYSetup(crypto*, unsigned int, e_role, e_mt_gen_alg) 0xdc)[0x4f81cc]
./bin/sha1.exe(ABYParty::Init() 0x74)[0x4e97d4]
./bin/sha1.exe(ABYParty::ABYParty(e_role, char*, SECURITYLEVELS, unsigned int, unsigned int, e_mt_gen_alg, unsigned int, unsigned short) 0x1f7)[0x4e9017]
./bin/sha1.exe(test_sha1_circuit(e_role, char*, SECURITYLEVELS, unsigned int, unsigned int, e_mt_gen_alg, e_sharing) 0xc2)[0x471732]
./bin/sha1.exe(main 0x129)[0x476329]
/usr/lib/libc.so.6(__libc_start_main 0xf1)[0x7fdfef218291]
./bin/sha1.exe(_start 0x2a)[0x47159a]
======================
======================
calling pthread_create (2)
----------------------
./bin/sha1.exe(CThread::Start() 0xfd)[0x4818dd]
./bin/sha1.exe(ABYSetup::Init() 0x111)[0x4f83a1]
./bin/sha1.exe(ABYSetup::ABYSetup(crypto*, unsigned int, e_role, e_mt_gen_alg) 0xdc)[0x4f81cc]
./bin/sha1.exe(ABYParty::Init() 0x74)[0x4e97d4]
./bin/sha1.exe(ABYParty::ABYParty(e_role, char*, SECURITYLEVELS, unsigned int, unsigned int, e_mt_gen_alg, unsigned int, unsigned short) 0x1f7)[0x4e9017]
./bin/sha1.exe(test_sha1_circuit(e_role, char*, SECURITYLEVELS, unsigned int, unsigned int, e_mt_gen_alg, e_sharing) 0xc2)[0x471732]
./bin/sha1.exe(main 0x129)[0x476329]
/usr/lib/libc.so.6(__libc_start_main 0xf1)[0x7fdfef218291]
./bin/sha1.exe(_start 0x2a)[0x47159a]
======================
======================
calling pthread_create (3)
----------------------
./bin/sha1.exe(CThread::Start() 0xfd)[0x4818dd]
./bin/sha1.exe(ABYParty::Init() 0x11f)[0x4e987f]
./bin/sha1.exe(ABYParty::ABYParty(e_role, char*, SECURITYLEVELS, unsigned int, unsigned int, e_mt_gen_alg, unsigned int, unsigned short) 0x1f7)[0x4e9017]
./bin/sha1.exe(test_sha1_circuit(e_role, char*, SECURITYLEVELS, unsigned int, unsigned int, e_mt_gen_alg, e_sharing) 0xc2)[0x471732]
./bin/sha1.exe(main 0x129)[0x476329]
/usr/lib/libc.so.6(__libc_start_main 0xf1)[0x7fdfef218291]
./bin/sha1.exe(_start 0x2a)[0x47159a]
======================
======================
calling pthread_create (4)
----------------------
./bin/sha1.exe(CThread::Start() 0xfd)[0x4818dd]
./bin/sha1.exe(ABYParty::Init() 0x11f)[0x4e987f]
./bin/sha1.exe(ABYParty::ABYParty(e_role, char*, SECURITYLEVELS, unsigned int, unsigned int, e_mt_gen_alg, unsigned int, unsigned short) 0x1f7)[0x4e9017]
./bin/sha1.exe(test_sha1_circuit(e_role, char*, SECURITYLEVELS, unsigned int, unsigned int, e_mt_gen_alg, e_sharing) 0xc2)[0x471732]
./bin/sha1.exe(main 0x129)[0x476329]
/usr/lib/libc.so.6(__libc_start_main 0xf1)[0x7fdfef218291]
./bin/sha1.exe(_start 0x2a)[0x47159a]
======================
======================
calling pthread_create (5)
----------------------
./bin/sha1.exe(CThread::Start() 0xfd)[0x4818dd]
./bin/sha1.exe(ABYParty::EstablishConnection() 0x1a9)[0x4ea319]
./bin/sha1.exe(ABYParty::ABYParty(e_role, char*, SECURITYLEVELS, unsigned int, unsigned int, e_mt_gen_alg, unsigned int, unsigned short) 0x4fc)[0x4e931c]
./bin/sha1.exe(test_sha1_circuit(e_role, char*, SECURITYLEVELS, unsigned int, unsigned int, e_mt_gen_alg, e_sharing) 0xc2)[0x471732]
./bin/sha1.exe(main 0x129)[0x476329]
/usr/lib/libc.so.6(__libc_start_main 0xf1)[0x7fdfef218291]
./bin/sha1.exe(_start 0x2a)[0x47159a]
======================
======================
calling pthread_create (6)
----------------------
./bin/sha1.exe(CThread::Start() 0xfd)[0x4818dd]
./bin/sha1.exe(ABYParty::EstablishConnection() 0x1c6)[0x4ea336]
./bin/sha1.exe(ABYParty::ABYParty(e_role, char*, SECURITYLEVELS, unsigned int, unsigned int, e_mt_gen_alg, unsigned int, unsigned short) 0x4fc)[0x4e931c]
./bin/sha1.exe(test_sha1_circuit(e_role, char*, SECURITYLEVELS, unsigned int, unsigned int, e_mt_gen_alg, e_sharing) 0xc2)[0x471732]
./bin/sha1.exe(main 0x129)[0x476329]
/usr/lib/libc.so.6(__libc_start_main 0xf1)[0x7fdfef218291]
./bin/sha1.exe(_start 0x2a)[0x47159a]
======================
======================
calling pthread_create (7)
----------------------
./bin/sha1.exe(CThread::Start() 0xfd)[0x4818dd]
./bin/sha1.exe(ABYParty::EstablishConnection() 0x1e3)[0x4ea353]
./bin/sha1.exe(ABYParty::ABYParty(e_role, char*, SECURITYLEVELS, unsigned int, unsigned int, e_mt_gen_alg, unsigned int, unsigned short) 0x4fc)[0x4e931c]
./bin/sha1.exe(test_sha1_circuit(e_role, char*, SECURITYLEVELS, unsigned int, unsigned int, e_mt_gen_alg, e_sharing) 0xc2)[0x471732]
./bin/sha1.exe(main 0x129)[0x476329]
/usr/lib/libc.so.6(__libc_start_main 0xf1)[0x7fdfef218291]
./bin/sha1.exe(_start 0x2a)[0x47159a]
======================
======================
calling pthread_create (8)
----------------------
./bin/sha1.exe(CThread::Start() 0xfd)[0x4818dd]
./bin/sha1.exe(ABYParty::EstablishConnection() 0x200)[0x4ea370]
./bin/sha1.exe(ABYParty::ABYParty(e_role, char*, SECURITYLEVELS, unsigned int, unsigned int, e_mt_gen_alg, unsigned int, unsigned short) 0x4fc)[0x4e931c]
./bin/sha1.exe(test_sha1_circuit(e_role, char*, SECURITYLEVELS, unsigned int, unsigned int, e_mt_gen_alg, e_sharing) 0xc2)[0x471732]
./bin/sha1.exe(main 0x129)[0x476329]
/usr/lib/libc.so.6(__libc_start_main 0xf1)[0x7fdfef218291]
./bin/sha1.exe(_start 0x2a)[0x47159a]
======================
======================
calling pthread_create (9)
----------------------
./bin/sha1.exe(CThread::Start() 0xfd)[0x4818dd]
./bin/sha1.exe(OTExtSnd::start_send(unsigned int) 0x276)[0x483ce6]
./bin/sha1.exe(OTExtSnd::send(unsigned long, unsigned long, unsigned long, CBitVector**, snd_ot_flavor, rec_ot_flavor, unsigned int, MaskingFunction*) 0xee)[0x4839de]
./bin/sha1.exe(ABYSetup::ThreadRunIKNPSnd(unsigned int) 0x10d)[0x4f8e0d]
./bin/sha1.exe(ABYSetup::CWorkerThread::ThreadMain() 0x81)[0x4f9d21]
./bin/sha1.exe(CThread::ThreadMainHandler(void*) 0x1e)[0x481f9e]
/usr/lib/libpthread.so.0( 0x7454)[0x7fdff0732454]
/usr/lib/libc.so.6(clone 0x5f)[0x7fdfef2e07df]
======================
======================
calling pthread_create (10)
----------------------
./bin/sha1.exe(CThread::Start() 0xfd)[0x4818dd]
./bin/sha1.exe(OTExtRec::start_receive(unsigned int) 0x270)[0x47f6b0]
./bin/sha1.exe(OTExtRec::receive(unsigned long, unsigned long, unsigned long, CBitVector*, CBitVector*, snd_ot_flavor, rec_ot_flavor, unsigned int, MaskingFunction*) 0x100)[0x47f3b0]
./bin/sha1.exe(ABYSetup::ThreadRunIKNPRcv(unsigned int) 0x106)[0x4f8f76]
./bin/sha1.exe(ABYSetup::CWorkerThread::ThreadMain() 0x99)[0x4f9d39]
./bin/sha1.exe(CThread::ThreadMainHandler(void*) 0x1e)[0x481f9e]
/usr/lib/libpthread.so.0( 0x7454)[0x7fdff0732454]
/usr/lib/libc.so.6(clone 0x5f)[0x7fdfef2e07df]
======================
======================
calling pthread_join (9)
----------------------
./bin/sha1.exe(CThread::Wait() 0xec)[0x481a8c]
./bin/sha1.exe(OTExtSnd::start_send(unsigned int) 0x2fc)[0x483d6c]
./bin/sha1.exe(OTExtSnd::send(unsigned long, unsigned long, unsigned long, CBitVector**, snd_ot_flavor, rec_ot_flavor, unsigned int, MaskingFunction*) 0xee)[0x4839de]
./bin/sha1.exe(ABYSetup::ThreadRunIKNPSnd(unsigned int) 0x10d)[0x4f8e0d]
./bin/sha1.exe(ABYSetup::CWorkerThread::ThreadMain() 0x81)[0x4f9d21]
./bin/sha1.exe(CThread::ThreadMainHandler(void*) 0x1e)[0x481f9e]
/usr/lib/libpthread.so.0( 0x7454)[0x7fdff0732454]
/usr/lib/libc.so.6(clone 0x5f)[0x7fdfef2e07df]
======================
======================
calling pthread_join (10)
----------------------
./bin/sha1.exe(CThread::Wait() 0xec)[0x481a8c]
./bin/sha1.exe(OTExtRec::start_receive(unsigned int) 0x2f6)[0x47f736]
./bin/sha1.exe(OTExtRec::receive(unsigned long, unsigned long, unsigned long, CBitVector*, CBitVector*, snd_ot_flavor, rec_ot_flavor, unsigned int, MaskingFunction*) 0x100)[0x47f3b0]
./bin/sha1.exe(ABYSetup::ThreadRunIKNPRcv(unsigned int) 0x106)[0x4f8f76]
./bin/sha1.exe(ABYSetup::CWorkerThread::ThreadMain() 0x99)[0x4f9d39]
./bin/sha1.exe(CThread::ThreadMainHandler(void*) 0x1e)[0x481f9e]
/usr/lib/libpthread.so.0( 0x7454)[0x7fdff0732454]
/usr/lib/libc.so.6(clone 0x5f)[0x7fdfef2e07df]
======================
Plaintext output: 
dc2172e79fae05b55178d431cd03262b0b45270
Testing SHA1 hash in Bool sharing: 
(0) Server Input:	fde4fbae4a09e020eff722969f83832b141cb2193eab67101d177fa95249c8ca
(0) Client Input:	de63b7f21d2a67d8b91953b9ea3bc26e78c5ccba10c7bff05dbee6ce8ccff78c
(0) Circ:	dc2172e709fae05b55178d431cd03262b0b45270
(0) Verify:	dc2172e709fae05b55178d431cd03262b0b45270
======================
calling pthread_join (3)
----------------------
./bin/sha1.exe(CThread::Wait() 0xec)[0x481a8c]
./bin/sha1.exe(ABYParty::Cleanup() 0x275)[0x4eaa15]
./bin/sha1.exe(ABYParty::~ABYParty() 0x39)[0x4ea6a9]
./bin/sha1.exe(test_sha1_circuit(e_role, char*, SECURITYLEVELS, unsigned int, unsigned int, e_mt_gen_alg, e_sharing) 0xa88)[0x4720f8]
./bin/sha1.exe(main 0x129)[0x476329]
/usr/lib/libc.so.6(__libc_start_main 0xf1)[0x7fdfef218291]
./bin/sha1.exe(_start 0x2a)[0x47159a]
======================
======================
calling pthread_join (4)
----------------------
./bin/sha1.exe(CThread::Wait() 0xec)[0x481a8c]
./bin/sha1.exe(ABYParty::Cleanup() 0x275)[0x4eaa15]
./bin/sha1.exe(ABYParty::~ABYParty() 0x39)[0x4ea6a9]
./bin/sha1.exe(test_sha1_circuit(e_role, char*, SECURITYLEVELS, unsigned int, unsigned int, e_mt_gen_alg, e_sharing) 0xa88)[0x4720f8]
./bin/sha1.exe(main 0x129)[0x476329]
/usr/lib/libc.so.6(__libc_start_main 0xf1)[0x7fdfef218291]
./bin/sha1.exe(_start 0x2a)[0x47159a]
======================
======================
calling pthread_join (5)
----------------------
./bin/sha1.exe(CThread::Wait() 0xec)[0x481a8c]
./bin/sha1.exe(SndThread::~SndThread() 0x2d)[0x4f16bd]
./bin/sha1.exe(SndThread::~SndThread() 0x19)[0x4f1739]
./bin/sha1.exe(ABYParty::Cleanup() 0x320)[0x4eaac0]
./bin/sha1.exe(ABYParty::~ABYParty() 0x39)[0x4ea6a9]
./bin/sha1.exe(test_sha1_circuit(e_role, char*, SECURITYLEVELS, unsigned int, unsigned int, e_mt_gen_alg, e_sharing) 0xa88)[0x4720f8]
./bin/sha1.exe(main 0x129)[0x476329]
/usr/lib/libc.so.6(__libc_start_main 0xf1)[0x7fdfef218291]
./bin/sha1.exe(_start 0x2a)[0x47159a]
======================
======================
calling pthread_join (6)
----------------------
./bin/sha1.exe(CThread::Wait() 0xec)[0x481a8c]
./bin/sha1.exe(SndThread::~SndThread() 0x2d)[0x4f16bd]
./bin/sha1.exe(SndThread::~SndThread() 0x19)[0x4f1739]
./bin/sha1.exe(ABYParty::Cleanup() 0x34a)[0x4eaaea]
./bin/sha1.exe(ABYParty::~ABYParty() 0x39)[0x4ea6a9]
./bin/sha1.exe(test_sha1_circuit(e_role, char*, SECURITYLEVELS, unsigned int, unsigned int, e_mt_gen_alg, e_sharing) 0xa88)[0x4720f8]
./bin/sha1.exe(main 0x129)[0x476329]
/usr/lib/libc.so.6(__libc_start_main 0xf1)[0x7fdfef218291]
./bin/sha1.exe(_start 0x2a)[0x47159a]
======================

One problem: While SndThread joins the underlying thread on destruction, RcvThread does not do so.

Destructor of SndThread

	~SndThread() {
		kill_task();
		this->Wait();
	}
	;

Destructor of RcvThread

	~RcvThread() {
		//this->Kill();
		delete rcvlock;
		free(listeners);
	}
	;

Strings comparison

Hello,

I'm thinking in make the TODO related with the use strings in the library, someone can give me guidance regarding this topic? Is the project owner interested in such evolution?

Does PutB2AGate() work as a SIMD gate?

Does PutB2AGate() work as a SIMD gate?

I have a circuit that implements a function involving some muxes, xors, and equality tests, and concludes with a multiplication. This is done with SIMD gates. Everything works great if I use a Boolean circuit. Now I want to do the last multiplication using arithmetic shares.

The problem is that the call to PutB2AGate on one wire messes up the result of that call on the other one. More concretely, the code below prints an array of "garbage", while if I comment out line 3 I see the correct value of variable srv_count_arith (circ and a_circ are a Boolean and an arithmetic circuit, respectively).

share *srv_count_arith;
share *cli_counts_arith;
cli_counts_arith = a_circ->PutB2AGate(cli_counts);
srv_count_arith = a_circ->PutB2AGate(srv_count);
circ->PutPrintValueGate(srv_count, "server value (bool)");
a_circ->PutPrintValueGate(srv_count_arith, "server value (arith)");

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.