NaCl/Windows
To use NaCl cryptography on Windows, there are two options:
- Use a C#/.Net port
- Compile the original NaCl code on Windows
A native compile of the original sourcecode will usually give the best results in terms of speed and resemblance to the original library. To make compiling NaCl on windows somewhat less painful, I've written a shellscript that extracts/creates all files needed, including a VS.Net/VisualC++.Net 9 project file.
Note that currently the build script does not support any platform specific optimized implementations of the cryptographic primitives. As a result, performance is usually comparable to or worse than the performance of the C#/.Net code.
The script currently compiles all reference implementations, but only exports a limited set. If anything you need is not exported, this is easy to change by editing the .def file.
The output of this script may also be useful to build the NaCl code for other previously unsupported platforms. It creates a file names sources.lst, which lists all the C source code files to compile. Don't forget to add the (generated) includes directory to the include path.
#!/bin/sh -e top="`pwd`/build/windows" include="$top/include" source="$top/source" export LANG=C rm -rf "$top" mkdir -p "$top" mkdir -p "$include" mkdir -p "$source" cp "randombytes/devurandom.h" "$include/randombytes.h" ( echo "#include <windows.h>" echo "#include <Wincrypt.h>" echo "#pragma comment(lib, \"crypt32.lib\")" echo "void randombytes(unsigned char * a,unsigned long long c) {" echo "HCRYPTPROV hProvider = 0;" echo "while (1) {" echo "if (!CryptAcquireContextW(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { Sleep(1); continue; }" echo "if (!CryptGenRandom(hProvider, (DWORD)c, (BYTE*)a)) { CryptReleaseContext(hProvider, 0); Sleep(1); continue; }" echo "CryptReleaseContext(hProvider, 0);" echo "break;" echo "}" echo "}" ) > "$source/randombytes.c" echo "source/randombytes.c" > "$top/sources.lst" macros=`cat MACROS` prototypesc=`cat PROTOTYPES.c` prototypescpp=`cat PROTOTYPES.cpp` cat OPERATIONS | while read o do [ -d "$o" ] || continue ls "$o" | sort | while read p do [ -d "$o/$p" ] || continue [ -f "$o/$p/used" ] || continue op="${o}_${p}" doth="$o/$p/ref/api.h" implementationdir=`dirname $doth` opi=`echo "$implementationdir" | tr ./- ___` language=c echo "$op" ( to="${source}/${op}" mkdir -p "$to" cd "$implementationdir" cfiles=`ls | grep '\.c$' || :` sfiles=`ls | grep '\.[sS]$' || :` ( echo "#ifndef ${o}_H" echo "#define ${o}_H" echo "" echo "#include \"${op}.h\"" echo "" echo "$macros" | egrep "${o}"'$|'"${o}"'\(|'"${o}"'_' | sed "s/$o/$op/" | while read mop do echo "#define ${mop} ${mop}" | sed "s/$op/$o/" done echo "#define ${o}_PRIMITIVE \"${p}\"" echo "#define ${o}_IMPLEMENTATION ${op}_IMPLEMENTATION" echo "#define ${o}_VERSION ${op}_VERSION" echo "" echo "#endif" ) > "${to}/${o}.h" ( echo "#ifndef ${op}_H" echo "#define ${op}_H" echo "" sed 's/[ ]CRYPTO_/ '"${opi}"'_/g' < api.h echo '#ifdef __cplusplus' echo '#include <string>' echo "$prototypescpp" | egrep "${o}"'$|'"${o}"'\(|'"${o}"'_' | sed "s/$o/$opi/" echo 'extern "C" {' echo '#endif' echo "$prototypesc" | egrep "${o}"'$|'"${o}"'\(|'"${o}"'_' | sed "s/$o/$opi/" echo '#ifdef __cplusplus' echo '}' echo '#endif' echo "" echo "$macros" | egrep "${o}"'$|'"${o}"'\(|'"${o}"'_' | sed "s/$o/$opi/" | while read mopi do echo "#define ${mopi} ${mopi}" | sed "s/$opi/$op/" done echo "#define ${op}_IMPLEMENTATION \"${implementationdir}\"" echo "#ifndef ${opi}_VERSION" echo "#define ${opi}_VERSION \"-\"" echo "#endif" echo "#define ${op}_VERSION ${opi}_VERSION" echo "" echo "#endif" ) > "${to}/${op}.h" for f in $cfiles $sfiles do echo "${op}_${f}" cp "$f" "${to}/${op}_${f}" echo "source/${op}/${op}_${f}" >> "$top/sources.lst" done cp -p "${to}/$op.h" "$include/$op.h" [ -f "../selected" ] || continue cp -p "${to}/$o.h" "$include/$o.h" ) done done ( echo "LIBRARY \"nacl\"" echo "EXPORTS" echo " crypto_box_curve25519xsalsa20poly1305_ref" echo " crypto_box_curve25519xsalsa20poly1305_ref_open" echo " crypto_box_curve25519xsalsa20poly1305_ref_keypair" echo " crypto_box_curve25519xsalsa20poly1305_ref_beforenm" echo " crypto_box_curve25519xsalsa20poly1305_ref_afternm" echo " crypto_box_curve25519xsalsa20poly1305_ref_open_afternm" ) > "$top/nacl.def" ( echo "<?xml version='1.0' encoding='Windows-1252'?>" echo "<VisualStudioProject ProjectType='Visual C++' Version='9,00' Name='nacl' RootNamespace='NaCl'>" echo "<Platforms><Platform Name='Win32' /></Platforms>" echo "<ToolFiles></ToolFiles>" echo "<Configurations>" echo "<Configuration Name='Release|Win32'" echo "OutputDirectory='\$(ProjectDir)\$(ConfigurationName)' IntermediateDirectory='\$(ConfigurationName)'" echo "ConfigurationType='2' CharacterSet='2' WholeProgramOptimization='1'>" echo "<Tool Name='VCCLCompilerTool' AdditionalIncludeDirectories='include\\' />" echo "<Tool Name='VCLinkerTool' ModuleDefinitionFile='nacl.def' />" echo "</Configuration>" echo "</Configurations>" echo "<References></References>" echo "<Files>" echo "<Filter Name='Source Files' Filter='cpp;c;s'>" sed "s_/_\\\\_g" "$top/sources.lst" | sed "s_^\\(.*\\)\$_<File RelativePath='\\1' />_" echo "</Filter>" echo "<File RelativePath='nacl.def' />" echo "</Files>" echo "<Globals></Globals>" echo "</VisualStudioProject>" ) > "$top/nacl.vcproj" rm "$top/sources.lst"