From Wiki
Revision as of 15:22, 4 January 2014 by Admin (Talk | contribs) (Fixed randombytes replacement)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

To use NaCl cryptography on Windows, there are two options:

  1. Use a C#/.Net port
  2. 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

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
	[ -d "$o" ] || continue
	ls "$o" | sort | while read p
		[ -d "$o/$p" ] || continue
		[ -f "$o/$p/used" ] || continue
		implementationdir=`dirname $doth`
		opi=`echo "$implementationdir" | tr ./- ___`
		echo "$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
					echo "#define ${mop} ${mop}" | sed "s/$op/$o/"
				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
					echo "#define ${mopi} ${mopi}" | sed "s/$opi/$op/"
				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
				echo "${op}_${f}"
				cp "$f" "${to}/${op}_${f}"
				echo "source/${op}/${op}_${f}" >> "$top/sources.lst"

			cp -p "${to}/$op.h" "$include/$op.h"

			[ -f "../selected" ]  || continue
			cp -p "${to}/$o.h" "$include/$o.h"

	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"