Linux
The Crypto++ mailing list occasionally receives questions regarding library use on various Linux platforms. This page will attempt to help folks working with Linux.
On Linux, Crypto++ is named libcryptopp. The makefile (discussed below) will create and install libcryptopp.a and libcryptopp.so. libcryptopp.a is a traditional static library, while libcryptopp.so is a shared object. Note: libcryptopp should not be confused with libcrypto (libcrypto is OpenSSL).
Linux shared objects written in C++ can be tricky since exceptions must cross the executable/shared object boundary for proper program execution. Those using a Crypto++ shared object should read Note for Shared Object Callers.
Crypto++ FIPS validation does not apply to Linux modules. This is because a Crypto++ binary was validated on Windows as a compiled DLL, and not in source form.
A separate page is available for using Crypto++ under Apple's Xcode. See iOS for building Crypto++ as a static library.
Finally, many thanks to the folks who helped with this page, including (but definitely not limited to) Zooko Wilcox O'Hearn, Nathan Phillip Brink, Alexey Kurov, Jonathan Wakely, Ian Lance Taylor, and Jens Peter Secher.
Fetch the Library
There are two ways to get Crypto++ on a Linux machine. The first is to download Crypto++ from the website (or SourceForge/SVN). The second is to install Crypto++ from a package provided by a distribution such as Debian, Fedora, Mandrivia, OpenSuse, or Ubuntu (see Linux Distributions Offering Crypto++ below).
When Crypto++ releases a version, a ZIP file is created an placed on the website for download. For example, the Crypto++ 5.6.1 ZIP was placed in the download area in August 2010 after revision 521 (the version change and tag). The 5.6.1 ZIP file is fixed in time and does not include the latest bug fixes - it will always be cumulative up to revision 521. Inevitably, this means the Crypto++ ZIP files will become stale over time.
Crypto++ Website
Fetch the latest version of the library. Below, the download was saved in cryptopp
. Issue the following to extract the archive. -a handles the CR/LF conversions.
> cd cryptopp/ > unzip -a cryptopp561.zip
Move on to Build and Install the Library.
SourceForge Repository
Issue the following to fetch the latest Crypto++ code from the SourceForge SVN repository.
$svn checkout https://cryptopp.svn.sourceforge.net/svnroot/cryptopp/trunk/c5 cryptopp
I you only want Crypto++ up to a certain revision, perform the following. Below, a checkout of revision 496 is performed.
$svn checkout -r 496 https://cryptopp.svn.sourceforge.net/svnroot/cryptopp/trunk/c5 cryptopp-496
Distribution Package
Most distributions package the library as cryptopp (libcryptopp.a or libcryptopp.so), while Debian (and derivatives) use libcryptopp and libcrypto++. Other distributions, such as Red Hat and Mint, do not provide a Crypto++ package. If using a distribution's version of the library, be aware that you will most likely receive a shared object (libcryptopp.so) rather than a traditional archive (libcryptopp.a).
To develop with Crypto++ using a distribution's package, you usually need to install three packages: the library's base package, the development package, and the debug symbol package. For example, on Debian, the packages of interest are libcrypto++8, libcrypto++8-dbg, and libcrypto++-dev.
If using a distribution's shared object, please take time to read Note for Shared Object Callers.
apt-get
For apt-get distributions (Debian and derivatives such as Ubuntu), issue the following to locate the package name and install the package. Note that the dev or development version of the Crypto++ library was selected. Note that grep crypto++ might need to be changed to grep cryptopp.
root@bruno:/# apt-cache pkgnames | grep -i crypto++ libcrypto++-utils libcrypto++8 libcrypto++8-dbg libcrypto++-dev libcrypto++-doc root@bruno:/# apt-get install libcrypto++8 libcrypto++8-dbg libcrypto++-dev Reading package lists... Done Building dependency tree Reading state information... Done The following NEW packages will be installed: libcrypto++-dev libcrypto++8 libcrypto++8-dbg 0 upgraded, 3 newly installed, 0 to remove and 0 not upgraded. Need to get 10.7MB of archives. ...
yum
On distributions which use yum (such as Fedora), search for Crypto++ using yum:
# yum search crypto++ ============================== Matched: crypto++ =============================== pycryptopp.x86_64 : Python wrappers for the Crypto++ library cryptopp.i686 : Public domain C++ class library of cryptographic schemes cryptopp.x86_64 : Public domain C++ class library of cryptographic schemes cryptopp-devel.i686 : Header files and development documentation for cryptopp cryptopp-devel.x86_64 : Header files and development documentation for cryptopp cryptopp-doc.noarch : Documentation for cryptopp cryptopp-progs.x86_64 : Programs for manipulating cryptopp routines
Issue the following commands to install the library and header files:
> su - password: # yum install cryptopp cryptopp-devel
The cryptest.exe program is not installed with the library on Fedora. If you want the cryptest program, issue:
# yum install cryptopp cryptopp-progs
Build and Install the Library
Crypto++ comes with a makefile named GNUMakefile. The library does not use autoconf and friends, so there is no ./configure
. A detailed treatment of the makefile can be found at GNUmakefile.
Precompiled headers require more than simply defining USE_PRECOMPILED_HEADERS
. If you plan on using it, see Precompiled headers below.
Makefile
The default makefile is configured to build a static library (archive), release build (-DNDEBUG), and includes options for moderate optimizations (-O2) and debug symbols (-g2). Performance penalties (or lack of penalties) when using -g are discussed in How does the gcc -g option affect performance?.
The Crypto++ makefile uses a CXXFLAG
of -march=native
, so Crypto++ builds correctly for the platform. However, GCC prior to version 4.6 has bugs related to -march=native
. See, for example, LTO performance: -march=native isn't saved in COLLECT_GCC_OPTIONS.
If you are using pthreads, Crypto++ will add -pthread
to LDFLAGS
for Linux. The library does not add the _REENTRANT
flag to CFLAGS
. For GNU/Linux, both -pthread
and _REENTRANT
should be specified. See -pthread option and gcc -pthread should define _REENTRANT?.
If you plan to profile your program under GCC, then add the -p or -pg switch to the makefile for use by prof or gprof. See Options for Debugging Your Program or GCC and Profiling.
Make and Install
Issue make
to build the static library and cryptest program. To build the static archive, shared object, and test program, enter the following. There is no need for root at this point.
make static dynamic cryptest.exe
After the library successfully builds, run cryptest.exe v
and cryptest.exe tv all
to validate the library. See Self Tests on the Release Process page for more details.
If you plan on building and installing both the static and dynamic libraries, tell make to do so. Otherwise, libcryptopp.a and cryptest.exe will be built under a standard user account, and libcryptopp.so will be built as root during install.
$ make libcryptopp.a libcryptopp.so cryptest.exe ... $ ls *.so *.a *.exe cryptest.exe libcryptopp.a libcryptopp.so
Finally, install the library. By default, Crypto++ installs to /usr/local
, so you will root to install components.
$ sudo make install PREFIX=/usr/local mkdir -p /usr/local/include/cryptopp cp *.h /usr/local/include/cryptopp chmod 755 /usr/local/include/cryptopp chmod 644 /usr/local/include/cryptopp/*.h mkdir -p /usr/local/lib cp libcryptopp.a /usr/local/lib chmod 644 /usr/local/lib/libcryptopp.a mkdir -p /usr/local/bin cp cryptest.exe /usr/local/bin chmod 755 /usr/local/bin/cryptest.exe mkdir -p /usr/local/share/cryptopp cp -r TestData /usr/local/share/cryptopp cp -r TestVectors /usr/local/share/cryptopp chmod 755 /usr/local/share/cryptopp chmod 755 /usr/local/share/cryptopp/TestData chmod 755 /usr/local/share/cryptopp/TestVectors chmod 644 /usr/local/share/cryptopp/TestData/*.dat chmod 644 /usr/local/share/cryptopp/TestVectors/*.txt
Also see Installing the Library for more details on the options available to you during install.
OpenBSD
OpenBSD is not Linux (but an OpenBSD might find themselves here). If compiling and installing for OpenBSD, then the library must be installed into /usr/local
. If you install to /usr
, be prepared for a typical output of:
g++ -g3 -ggdb -O0 -pipe -fsigned-char -fmessage-length=0 -Woverloaded-virtual -Wreorder -Wformat=2 -Wformat-security -Wno-unused -fvisibility=hidden -fstack-protector -I. -I./esapi -I./deps -I/usr/local/include -fpic -c src/codecs/HTMLEntityCodec.cpp -o src/codecs/HTMLEntityCodec.o In file included from /usr//include/cryptopp/misc.h:4, from ./esapi/crypto/Crypto++Common.h:24, from src/codecs/HTMLEntityCodec.cpp:12: /usr//include/cryptopp/cryptlib.h:99: error: template with C linkage /usr//include/cryptopp/cryptlib.h:247: error: template with C linkage /usr//include/cryptopp/cryptlib.h:254: error: template with C linkage /usr//include/cryptopp/cryptlib.h:261: error: template with C linkage /usr//include/cryptopp/cryptlib.h:268: error: template with C linkage /usr//include/cryptopp/cryptlib.h:293: error: template with C linkage /usr//include/cryptopp/cryptlib.h:698: error: template with C linkage
Precompiled Headers
Use of precompiled headers is framed out in Crypto++, but the feature requires a few tweaks for Linux. Using precompiled headers on a Core 2 Duo (circa late-2008) reduced compile times by 38% (3 min, 51 sec versus 2 min, 22 sec). On a Core i7 machine (circa mid-2010) the time was reduced by 24% to just under 2 minutes. Note that GCC must be version 3.4 or hight to support the feature.
To use precompiled headers, modify pch.h by adding <string>, <algorithm>, and <memory> to the list of includes. This makes sense since string and auto_ptr are used frequently in Crypto++ and therefore benefit from precompilation.
Add USE_PRECOMPILED_HEADERS
to CXXFLAGS
. Note: this is a Crypto++ define, and is not required by GCC's implementation of precompiled headers.
CXXFLAGS = -DNDEBUG -g -O2 -DUSE_PRECOMPILED_HEADERS=1
Add a rule for precompile. The file name must have the extension .gch. The command must also use the same CXXFLAGS
as the files using precompiled header. Both are GCC requirements.
precompile: pch.h pch.cpp $(CXX) $(CXXFLAGS) pch.h -o pch.h.gch
Finally, edit GNUmakefile and add precompile as a dependency for targets all, libcryptopp.a, libcryptopp.so, and cryptest.exe. For example:
all: precompile cryptest.exe ... cryptest.exe: precompile libcryptopp.a $(TESTOBJS) $(CXX) -o $@ $(CXXFLAGS) $(TESTOBJS) -L. -lcryptopp $(LDFLAGS) $(LDLIBS)
To verify that precompiled headers are being used, add the following to pch.h. If one message is displayed, precompiled headers are in play. If 130 or so messages are displayed, Crypto++ is not using precompiled headers. Note: Stallman no longer objects to #pragma since it can be used in a macro.
#pragma message("Including Crypto++ precompiled header file.")
To benchmark the savings issue the following:
make clean && date && make && date
Also see Jason Smethers' comments on using ccache to reduce compilation times at Linux/GCC and Precompiled Headers.
A Crypto++ Program
The sample program below uses Crypto++'s Integer class. It was chosen because Integer overloads operator<<, which makes it convenient to exercise the library and display results with minimal effort.
Source Code
#include <iostream> using std::cout; using std::endl; #include "cryptopp/integer.h" using CryptoPP::Integer; int main( int, char** ) { Integer i; cout << "i: " << i << endl; return 0; }
The integer class has arbitrary precision, so a variable will easily handle large integers and other arithmetic operations such as the following.
int main( int, char** ) { Integer j("100000000000000000000000000000000"); j %= 1999; cout << "j: " << j << endl; return 0; }
Compiling and Linking
To compile and link the program issue the following. There are two points to observe when compiling and linking. First, use g++ rather than gcc (see GCC's Compiling C++ Programs). Second the library directive (-l) is the last argument to g++. Note: on some systems (for example, Fedora), the library option might be -lcrypto++.
g++ -DNDEBUG -g3 -O2 -Wall -Wextra -o test test.cpp -l:libcryptopp.a
-Wall
and -Wextra
turn on most warnings since its always a good idea to let static analysis tools catch mistakes early. (For reasons only known to the free software world, -Wall
only turns on some warnings, and not all warnings as the name implies.) -Wno-unused
increases the signal to noise ratio because Crypto++ has a lot of unused parameters, which is par for the course for an object oriented program with lots of interfaces.
If -Wall
and -Wextra
are producing too much noise (even after -Wno-unused
), compile with -fdiagnostics-show-option
to locate which additional warnings to suppress. See Options to Request or Suppress Warnings.
The -g3 switch adds maximum debug information to the executable test and is not required (note that -g is equivalent to -g2). The -ggdb adds gdb extensions which might prove useful when debugging non-trivial programs under gdb which support extensions. See Options for Debugging Your Program or GCC. If you are adding -ggdb
, you might consider adding -fno-omit-frame-pointer
so that stack traces from the field are easier to walk.
-O0
disables all optimizations, so even #define
's are available to the debugger. Usually, optimizations such as these are taken by the optimizer, and the debugger will display something similar to 'value optimized out'. Note that -O0
is the default optimization level.
-o specifies the output file name. -l specifies the library. When using -l, we only need to specify the base library name. ld will prepend lib and append .a (or .so) when searching for the library (reference the ld man pages around line 6200). Finally, the -l option location is significant (libraries must be specified last).
The -l:filename
tells the linker to use the exact library name. It allows you to easily specify the static archive using -l:libcryptopp.a
, and avoid shared objects. You will not suffer Linux path problems that have existed for the last 20 years or so if you use it.
Running the Program
To run the program, specify the current working directory in case test is a program in /usr/bin
.
./test
Output should be as below.
i: 0.
If we were to run the variant 100000000000000000000000000000000 % 1999, we would receive the expected result of 820.
Stripping Debug Symbols
If the program was compiled and linked with debug symbols, strip can be used to remove the symbols. Once stripped, debuggers and stack traces are generally useless.
> ls -l myprogram ... 6866924 2009-04-28 16:12 myprogram > strip --strip-debug myprogram > ls -l myprogram ... 1738761 2009-04-28 16:13 myprogram
Also see Debug Symbols for how to create two part executables on Linux. A two part executable is a stripped executable and its debug information file (symbol file, similar to a Microsoft PDB).
Crypto++ Libraries
In general, try to use the static version of the Crypto++ library (libcryptopp.a or libcryptopp.a) rather than the shared object.
When building from the makefile, the library name will be either libcryptopp.a or libcryptopp.so (depending on the make target). For distributions which provide a Crypto++ library package, there seems to be two predominant shared object names: libcryptopp.{a|so} and libcrypto++.{a|so}. For example, systems running Fedora or OpenSuse will use libcryptopp.so, while Debian and Ubuntu will offer libcrypto++.so.
C++ based shared objects under GNU Linux usually leaves something to to be desired. If you have problems with two separate libraries each loading Crypto++ as s shared object, see:
- C++ One Definition Rule (cause of many double free's)
- dynamic_cast, throw, typeid don't work with shared libraries (the GCC FAQ entry for the behavioral change in the 3.0 ABI)
- Minimal GCC/Linux shared lib + EH bug example (consequence of documented behavior)
- dlopen and placing exception body in .cpp file (consequence of documented behavior)
- Errors with multiple loading cryptopp as shared lib on Linux (ODR hardening at version 5.6.1 with commits 488, et al)
- Global variable in static library - double free or corruption error (consequence of documented behavior)
- Comparing types across DSOs (sic) (consequence of documented behavior)
- RTLD_GLOBAL and libcryptopp.so crash (ODR hardening at version 5.6.1 with commits 488, et al)
- pycryptopp Ticket 44 (Python module loading of Crypto++ dynamic library) (using
RTLD_GLOBAL
breaks glibc, includes a python script and test cases)
libcryptopp.a
libcryptopp.a is the static version of the Crypto++ library. The Crypto++ makefile will build and install the static library in response to make install. Since the library is typically on a known path for the linker (see below), there is usually no need for the -L option to ld.
> whereis libcryptopp.a libcryptopp: /usr/lib/libcryptopp.a
The GNU linker has a nice option of the form -l:filename
. It tells the linker to use the exact library name. It allows you to easily specify the static archive using -l:libcryptopp.a
, and avoid shared objects. You will not suffer Linux path problems that have existed for the last 20 years or so if you use it.
libcryptopp.so
libcryptopp.so is the shared object version of the Crypto++ library (dynamic version in Windows parlance). The makefile added the libcryptopp.so target at commit 496. Revision 496 is included in the 5.6.1 ZIP archive on the website.
Though Crypto++ now supports building a shared object, Crypto++ versions 5.6.0 and prior did not support shared objects and the makefile did not include the target. Zooko Wilcox-O'Hearn, author of the Tahoe File System (a secure, decentralized, fault-tolerant file system), has posted a patch for building Crypto++ as a shared object. See Patch: build libcryptopp.so. In addition, Zooko offers information on using Debian and Fedora's prebuilt libcryptopp.so.
Users of the shared object should familiarize themselves with Note for Shared Object Callers, and package maintainers should read Note for Distribution Packagers below.
Note for Shared Object Callers and Note for Distribution Packagers discuss some circumstances required to crash a shared object (C++ shared object, RTLD_GLOBAL
, global objects with destructors, and violation of C++'s One Definition Rule). Use of global variables are inevitable, and Crypto++ attempts to use them in a library-safe manner.
Auditing the library for use of global variables began when Crypto++ added official support for shared objects. Unfortunately, it does not appear that gcc offers a switch to audit for use of globals. A feature request for the switch was submitted in October, 2010. See Switch to warn of global variables in a C++ shared object.
In the absence of an official auditing method, Crypto++ tries to use consistent naming, with global variables specified with a g_ prefix. Ian Taylor suggests using objdump and objdump -t -j .data | grep ' g '. nm -D /usr/lib/cryptopp.so | grep g_ can also be used to audit use of global variables in the library. See Audit Use of Global Variables in C++ Shared Object (GCC Warning?).
Callers which dynamically load libcryptopp.so or libcrypto++.so should use the RTLD_GLOBAL
flag in dlopen. If the call to dlopen fails, OR in RTLD_LAZY
and try again. According to the Open Group Base Specifications of dlopen, a third option of interest exists, but we've never had to use it: RTLD_NOW
. If the first two tries fail, RTLD_GLOBAL | RTLD_NOW
probably will not hurt.
RTLD_GLOBAL
is required so that a module can correctly catch a Crypto++ exception. The reason for the flags is the new C++ ABI and the GCC 3.0 [and above] series of tools use address comparisons, rather than string comparisons, to determine type equality. See dynamic_cast, throw, typeid don't work with shared libraries.
The flags passed to dlopen (RTLD_GLOBAL
, RTLD_LAZY
, and RTLD_NOW
) have been determined through trial and error, and is being passed on in folklore fashion (there's some wiggle room in the Open Group Base Specifications of dlopen). For example, Fedora and OpenSuse appear to accept just RTLD_GLOBAL
, while Debian and Ubuntu seem to require RTLD_GLOBAL | RTLD_LAZY
.
Since your program might run on systems which use either libcryptopp.so or libcrypto++.so, the following might be a helpful strategy for dynamic loading. In fact, Cryptopp-SO-Test.zip uses similar to ensure the Crypto++ shared object is located regardless of Linux distribution or dlopen behavior.
void* cryptlib = NULL; cryptlib = dlopen("libcryptopp.so", RTLD_GLOBAL); if(!cryptlib) cryptlib = dlopen("libcryptopp.so", RTLD_GLOBAL | RTLD_LAZY); if(!cryptlib) cryptlib = dlopen("libcrypto++.so", RTLD_GLOBAL); if(!cryptlib) cryptlib = dlopen("libcrypto++.so", RTLD_GLOBAL | RTLD_LAZY); if(!cryptlib) throw runtime_error("Failed to load crypto++ shared object"); ... dlclose(cryptlib);
Android 6.0 changed share object loading behavior, so you may also need to try with RTLD_LOCAL
also. See Android 6.0 Changes | Runtime for details.
Finally, Zooko Wilcox O'Hearn reports that Python test cases occasionally fail when using RTLD_GLOBAL
. Zooko's work around was to drop the flag. Open questions include 'Does this imply RTLD_LOCAL
', and 'Is this behavior limited to Ubuntu'. See [Tahoe LAFS] Changeset 711. So much for planning based on documentation.
Note for Distribution Packagers
The following should probably be in a separate FAQ for packagers and patchers.
Bug Fixes and Releases
If you are a package maintainer and would like to know of bug fixes, releases, and other interesting events which might warrant a package update, please add your email address to the list on the Linux Talk page.
Master is Current and Stable
Crypto++ keeps Master stable. You can just about always checkout master and use anything from it.
Unfortunately, Crypto++ does not back port because it does not maintain release branches.
Crypto++ X.Y.Z ZIP is Fixed
When Crypto++ releases a version, a ZIP file is created and placed on the website for download. For example, the Crypto++ 5.6.1 ZIP was placed in the download area in August 2010 after a commit of revision 521. The 5.6.1 ZIP file is fixed in time and does not include the latest bug fixes - it will always be cumulative up to revision 521. Inevitably, all ZIP files will become stale over time.
Library Validation and Benchmarks
After building the Crypto++ library, please issue cryptest.exe v to verify the library. More comprehensice tests are available with cryptest.exe tv all. Run cryptest.exe b to run the benchmarks.
cryptest.exe v
To validate the Crypto++ library, one runs cryptest.exe v. However, cryptest.exe makes assumptions about the location of its test data. After cryptest.exe has been installed in /usr/bin or /usr/local/bin, the assumptions no longer hold true and the validation no longer works. A patch is now available, and it can be found at DataDir patch.
Linux Distributions
The following offers helpful information when using packages provided by the distribution.
Distributions Offering Crypto++
Crypto++ does not offer RPMs or DEBs. Each distribution performs its own packaging.
Distribution | Library Name | Package Information |
---|---|---|
Debian | libcrypto++ | http://packages.debian.org/search?keywords=crypto%2B%2B |
CentOS 6 | libcryptopp | Requires EPEL6 testing repository. See http://fedoraproject.org/wiki/EPEL |
Fedora | libcryptopp | http://koji.fedoraproject.org/koji/packageinfo?packageID=7023 |
Mandriva | libcryptopp | http://doc4.mandriva.org/bin/view/d4/search?name=cryptopp&opc=component |
OpenSuse | libcryptopp | http://software.opensuse.org/search?q=cryptopp&baseproject=openSUSE%3AFactory |
Red Hat 5 | Not included | http://ftp.redhat.com/pub/redhat/linux/enterprise/5Client/en/os/SRPMS/ |
Red Hat 6 | libcryptopp | Requires EPEL6 testing repository. See http://fedoraproject.org/wiki/EPEL |
Scientific Linux | libcryptopp | Requires EPEL6 testing repository. See http://fedoraproject.org/wiki/EPEL |
Ubuntu | libcrypto++ | http://packages.ubuntu.com/search?keywords=crypto%2B%2B |
The list above is not complete, is listed in alphabetical order, and not meant to insult unlisted distributions. The table includes Red Hat because it is popular in the enterprise. The table was compiled using the top 5 or so distributions from Linux Distributions - Facts and Figures at distrowatch.com.
Distribution Package Version
The dpkg
command can be used to determine the version of Crypto++ installed on a system using apt-get and friends.
$ apt-cache pkgnames | grep -i crypto++ libcrypto++-utils libcrypto++8 libcrypto++8-dbg libcrypto++-dev libcrypto++-doc $ dpkg -s libcrypto++8 Package: libcrypto++8 Status: install ok installed Priority: optional Section: libs Installed-Size: 4900 Maintainer: Ubuntu Developers Architecture: amd64 Source: libcrypto++ Version: 5.6.0-5 Depends: libc6 (>= 2.4), libgcc1 (>= 1:4.1.1), libstdc++6 (>= 4.2.1) Description: General purpose cryptographic library - shared library General purpose cryptographic library for C++. This package contains the shared libraries and should only be installed if other packages depend on it. Original-Maintainer: Jens Peter Secher <[email protected]> Homepage: http://www.cryptopp.com
GNU Linux versioning usually leaves a lot to be desired. Some distributions use the library name and Crypto++ library version to form a package name and file names (for example, libcryptopp-5.6.0.so). Other distributions use the library name and base system version (for example, libcryptopp-fc13.so) for package and file names. And the situation only gets worst as fixes are back-ported while leaving package names, versions, and file names unchanged.
To show package related information, use apt-cache
.
$ apt-cache showpkg libcrypto++8 Package: libcrypto++8 Versions: 5.6.0-5 (/var/lib/apt/lists/us.archive.ubuntu.com_ubuntu_dists_lucid_universe_binary-amd64_Packages) (/var/lib/dpkg/status) Description Language: File: /var/lib/apt/lists/us.archive.ubuntu.com_ubuntu_dists_lucid_universe_binary-amd64_Packages MD5: 81fdf53fa3eb3f0f338e2c29ca70b7aa Reverse Depends: kvirc,libcrypto++8 python-pycryptopp-dbg,libcrypto++8 python-pycryptopp,libcrypto++8 libcrypto++8-dbg,libcrypto++8 5.6.0-5 libcrypto++-utils,libcrypto++8 libcrypto++-dev,libcrypto++8 5.6.0-5 kvirc,libcrypto++8 amule-utils-gui,libcrypto++8 amule-daemon,libcrypto++8 amule-adunanza-utils-gui,libcrypto++8 amule-adunanza-daemon,libcrypto++8 amule-adunanza,libcrypto++8 amule,libcrypto++8 Dependencies: 5.6.0-5 - libc6 (2 2.4) libgcc1 (2 1:4.1.1) libstdc++6 (2 4.2.1) Provides: 5.6.0-5 -
For systems using yum, use info to display Crypto++ package information:
# yum info cryptopp updates/metalink | 17 kB 00:00 updates-debuginfo/metalink | 14 kB 00:00 updates-source/metalink | 15 kB 00:00 Installed Packages Name : cryptopp Arch : x86_64 Version : 5.6.1 Release : 3.fc14 Size : 5.4 M Repo : installed From repo : updates Summary : Public domain C++ class library of cryptographic schemes URL : http://www.cryptopp.com/ License : Public Domain Description : Crypto++ Library is a free C++ class library of cryptographic : schemes. See http://www.cryptopp.com/ for a list of supported : algorithms. : : One purpose of Crypto++ is to act as a repository of public domain : (not copyrighted) source code. Although the library is copyrighted : as a compilation, the individual files in it are in the public : domain. ...
Examining the Library
This section covers usage of objdump and nm to examine symbols and code generation. See Ten Commands Every Linux Developer Should Know. If you are working on Mac OS X, use otool -afhv <obj file>.
Examining Code
To examine the generated code, use objview or dissy (a visual front end to objview). Below, objview displays the file header.
user@studio:~$ objdump -f rsa_kgen.exe rsa_kgen.exe: file format elf64-x86-64 architecture: i386:x86-64, flags 0x00000112: EXEC_P, HAS_SYMS, D_PAGED start address 0x0000000000404dd0
To disassemble a function, use the -d switch.
user@studio:~$ objdump -d rsa_kgen.exe 0x4049a8 rsa_kgen.exe: file format elf64-x86-64 Disassembly of section .init: 00000000004049a8 <_init>: 4049a8: 48 83 ec 08 sub $0x8,%rsp 4049ac: e8 4b 04 00 00 callq 404dfc <call_gmon_start> 4049b1: e8 da 04 00 00 callq 404e90 <frame_dummy> 4049b6: e8 25 3d 00 00 callq 4086e0 <__do_global_ctors_aux> 4049bb: 48 83 c4 08 add $0x8,%rsp 4049bf: c3 retq
Similar to nm (discussed below), we can also dump decorated symbols.
user@studio:~$ objdump -t rsa_kgen.exe | grep Integer 000000000060c260 w O .bss 0000000000000038 _ZTVN8CryptoPP7IntegerE 0000000000406e5a w F .text 0000000000000048 _ZNK8CryptoPP23TrapdoorFunctionInverse26CalculateRandomizedInverseERNS_21RandomNumberGeneratorERKNS_7IntegerE 0000000000000000 F *UND* 0000000000000000 _ZN8CryptoPP7IntegerC1ERKS0_ 0000000000406cba w F .text 0000000000000047 _ZNK8CryptoPP16TrapdoorFunction23ApplyRandomizedFunctionERNS_21RandomNumberGeneratorERKNS_7IntegerE 0000000000000000 F *UND* 0000000000000000 _ZN8CryptoPP7IntegermmEv 0000000000000000 F *UND* 0000000000000000 _ZN8CryptoPP7IntegerC1Ev 0000000000406a8c w F .text 0000000000000075 _ZN8CryptoPP7IntegerD1Ev
Finally, we can clean up the output a bit with the following command.
user@studio:~$ objdump -t rsa_kgen.exe | grep Integer | cut --bytes=26-30,60- .bss _ZTVN8CryptoPP7IntegerE .text _ZNK8CryptoPP23TrapdoorFunctionInverse26CalculateRandomizedInverseERNS_21RandomNumberGeneratorERKNS_7IntegerE *UND* _ZN8CryptoPP7IntegerC1ERKS0_ .text _ZNK8CryptoPP16TrapdoorFunction23ApplyRandomizedFunctionERNS_21RandomNumberGeneratorERKNS_7IntegerE *UND* _ZN8CryptoPP7IntegermmEv *UND* _ZN8CryptoPP7IntegerC1Ev .text _ZN8CryptoPP7IntegerD1Ev
Examining Symbols
To dump the contents of the library, use the nm command. Note: if examining symbols from a shared object, you must inldue the -D or --dynamic option:
nm /usr/lib/cryptopp.a nm --dynamic /usr/lib/cryptopp.so
The command below dumps the library's exported symbols then filters based on "Integer". Output is not shown because of the number of lines in the output.
> nm /usr/lib/libcryptopp.a | grep 'Integer'
To dump the first eight demangled Integer entries from the library. Unused entries - those of type U - can be removed with option --defined-only
.
> nm --demangle /usr/lib/libcryptopp.a | grep 'Integer' | head -8 00000000 B CryptoPP::g_pAssignIntToInteger U CryptoPP::g_pAssignIntToInteger U CryptoPP::g_pAssignIntToInteger U CryptoPP::a_exp_b_mod_c(CryptoPP::Integer const&, CryptoPP::Integer const&, CryptoPP::Integer const&) 00000850 T CryptoPP::PublicBlumBlumShub::PublicBlumBlumShub(CryptoPP::Integer const&, CryptoPP::Integer const&) 00000b60 T CryptoPP::PublicBlumBlumShub::PublicBlumBlumShub(CryptoPP::Integer const&, CryptoPP::Integer const&) U CryptoPP::Integer::Integer(CryptoPP::Integer::Sign, unsigned long long) U CryptoPP::Integer::Integer(CryptoPP::Integer const&)
Below is a dump of unique Integer constructors offered by the library. The command should be entered on a single line (the command spans two lines for readability). The --bytes=12- option instructs cut to remove bytes 0-11 by specifying 12 to End of Line ( 12- ). Note that the trailing dash of 12- is not optional. sort performs an ascending sort, and uniq removes consecutive duplicates.
> nm --demangle --defined-only /usr/lib/libcryptopp.a | grep 'CryptoPP::Integer::Integer' | cut --bytes=12- | sort | uniq CryptoPP::Integer::Integer() CryptoPP::Integer::Integer(char const*) CryptoPP::Integer::Integer(CryptoPP::BufferedTransformation&) CryptoPP::Integer::Integer(CryptoPP::BufferedTransformation&, unsigned int, CryptoPP::Integer::Signedness) CryptoPP::Integer::Integer(CryptoPP::Integer const&) CryptoPP::Integer::Integer(CryptoPP::Integer::Sign, unsigned int, unsigned int) CryptoPP::Integer::Integer(CryptoPP::Integer::Sign, unsigned long long) CryptoPP::Integer::Integer(CryptoPP::RandomNumberGenerator&, unsigned int) CryptoPP::Integer::Integer(long) CryptoPP::Integer::Integer(unsigned char const*, unsigned int, CryptoPP::Integer::Signedness) CryptoPP::Integer::Integer(unsigned int, unsigned int) CryptoPP::Integer::Integer(wchar_t const*) [One contructor removed for screen formatting]
Finally, we can further clean up the output by specifying sed "s/CryptoPP:://g"
. The sed command will replace instances of "CryptoPP::" with an empty string.
> nm --demangle --defined-only /usr/lib/libcryptopp.a | grep 'CryptoPP::Integer::Integer' | cut --bytes=12- | sed "s/CryptoPP:://g" | sort | uniq Integer::Integer() Integer::Integer(BufferedTransformation&) Integer::Integer(BufferedTransformation&, unsigned int, Integer::Signedness) Integer::Integer(char const*) Integer::Integer(Integer const&) Integer::Integer(Integer::Sign, unsigned int, unsigned int) Integer::Integer(Integer::Sign, unsigned long long) Integer::Integer(long) Integer::Integer(RandomNumberGenerator&, unsigned int) Integer::Integer(unsigned char const*, unsigned int, Integer::Signedness) Integer::Integer(unsigned int, unsigned int) Integer::Integer(wchar_t const*) [One contructor removed for screen formatting]
x86 vs x64
The Crypto++ makefile uses a CXXFLAG of -march=native, so Crypto++ builds correctly for the platform. There are no special options required.
On x86 Linux, the traditional /usr/lib directory is used for the library. Some 64-bit Linux's, such as Debian and Ubuntu, use two directories: /usr/lib and /usr/lib64. Both /usr/lib and /usr/lib64 contain 64 bit libraries. Other distributions, such as Fedora, use only /usr/lib64 (see Alexey Yurov, Maintainer of Crypto++ on Fedora, response to Linux: makefile, install and x86_64). The Crypto++ makefile only installs to /usr/lib on x64 machines.
Below, we use objdump to examine a Ubuntu 10.04 installation. The -f option to objdump indicates we only want the header. When dumping the archive (libcryptopp.a), we use head to display the first 12 lines of output. Otherwise, we would get a complete dump since an archive is a collection of objects to be used by the linker.
user@studio:~$ whereis libcryptopp libcryptopp: /usr/lib/libcryptopp.so /usr/lib/libcryptopp.a /usr/lib64/libcrypto++.so /usr/lib64/libcrypto++.a user@studio:~$ objdump -f /usr/lib/libcryptopp.so /usr/lib/libcryptopp.so: file format elf64-x86-64 architecture: i386:x86-64, flags 0x00000150: HAS_SYMS, DYNAMIC, D_PAGED start address 0x000000000027f630 user@studio:~$ objdump -f /usr/lib/libcryptopp.a | head -12 In archive /usr/lib/libcryptopp.a: 3way.o: file format elf64-x86-64 architecture: i386:x86-64, flags 0x00000011: HAS_RELOC, HAS_SYMS start address 0x0000000000000000 adler32.o: file format elf64-x86-64 architecture: i386:x86-64, flags 0x00000011: HAS_RELOC, HAS_SYMS start address 0x0000000000000000 user@studio:~$ objdump -f /usr/lib64/libcrypto++.so /usr/lib64/libcrypto++.so: file format elf64-x86-64 architecture: i386:x86-64, flags 0x00000150: HAS_SYMS, DYNAMIC, D_PAGED start address 0x000000000027f630 user@studio:~$ objdump -f /usr/lib64/libcrypto++.a | head -12 In archive /usr/lib64/libcrypto++.a: 3way.o: file format elf64-x86-64 architecture: i386:x86-64, flags 0x00000011: HAS_RELOC, HAS_SYMS start address 0x0000000000000000 adler32.o: file format elf64-x86-64 architecture: i386:x86-64, flags 0x00000011: HAS_RELOC, HAS_SYMS start address 0x0000000000000000
Common Errors
This section covers common errors encountered when working with Cryto++.
gcc/g++/ld Versions
Verify you are using a supported version of the g++ and ld. Compare the results to the platform matrix on the Crypto++ homepage. In general, GCC 3.3 and above is supported for the latest versions of Crypto++ (5.4, 5.5, and 5.6).
> g++ --version g++ (SUSE Linux) 4.3.2 [gcc-4_3-branch revision 141291]
> ld --version GNU ld (GNU Binutils; openSUSE 11.1) 2.19
-l option
According to the g++ man pages (around line 25), the -l option location is significant:
For the most part, the order you use doesn't matter. Order does matter when you use several options of the same kind; for example, if you specify -L more than once, the directories are searched in the order specified. Also, the placement of the -l option is significant.
Also see the note regarding object link order in GCC Options for Linking.
If you receive an error similar to undefined reference to CryptoPP::Integer::Integer() or undefined reference to vtable for CryptoPP::Integer, you most likely specified the library as an early option to g++:
> g++ -lcryptopp -o test test.cpp # wrong!!!
We can verify the vtables are present using nm:
> nm --demangle --defined-only /usr/lib/libcryptopp.a | grep 'vtable for CryptoPP::Integer' | sort | uniq 00000000 V vtable for CryptoPP::Integer 00000000 V vtable for CryptoPP::Integer::DivideByZero 00000000 V vtable for CryptoPP::Integer::OpenPGPDecodeErr 00000000 V vtable for CryptoPP::Integer::RandomNumberNotFound
SHA-2 Crash and Binutils
If you experience a crash during validation (cryptest.exe v) and you are using the lates SVN code, verify your version of binutils. See "crytest v" hangs up and Conflict between Crypto++ 5.6.0 and GNU binutils 2.19.91.20091014-0ubuntu1.
GCC 4.5.2 Internal Compiler Error
If you experience an internal compiler error when using GCC 4.5.2 on Ubuntu 11.04:
$ make g++ -DNDEBUG -g -O2 -march=native -pipe -c 3way.cpp g++ -DNDEBUG -g -O2 -march=native -pipe -c adler32.cpp g++ -DNDEBUG -g -O2 -march=native -pipe -c algebra.cpp g++ -DNDEBUG -g -O2 -march=native -pipe -c algparam.cpp g++ -DNDEBUG -g -O2 -march=native -pipe -c arc4.cpp g++ -DNDEBUG -g -O2 -march=native -pipe -c asn.cpp asn.cpp: In member function ‘void CryptoPP::OID::DEREncode(CryptoPP::BufferedTransformation&) const’: asn.cpp:254:1: error: unrecognizable insn: (insn 194 178 195 2 asn.cpp:248 (set (reg:SI 2 cx) (mem:QI (plus:SI (reg/f:SI 1 dx [orig:61 D.44160 ] [61]) (const_int 4 [0x4])) [16 S1 A32])) -1 (nil)) asn.cpp:254:1: internal compiler error: in extract_insn, at recog.c:2104 Please submit a full bug report, with preprocessed source if appropriate. See <file:///usr/share/doc/gcc-4.5/README.Bugs> for instructions. make: *** [asn.o] Error 1
Then comment out the -mtune=native
in GNUMakefile:
cat GNUMakefile ... ifneq ($(GCC42_OR_LATER),0) ifeq ($(UNAME),Darwin) CXXFLAGS += -arch x86_64 -arch i386 else # CXXFLAGS += -march=native endif endif
stdlibc
If you start with an error regarding __static_initialization_and_destruction, with hundreds following, you most likely used gcc rather than g++:
> gcc -o test test.cpp -lcryptopp # wrong!!!
Undefined Crypto++ Type
If gcc/g++ does not recognize a Crypto++ type (such as CryptoPP::Integer), verify the correct header is being included and verify the CryptoPP namespace is being used. Finally, verify gcc/g++ header paths. To display the default search directories of GCC, try:
> echo "" | gcc -o /tmp/tmp.o -v -x c - > echo "" | g++ -o /tmp/tmp.o -v -x c++ -
Cannot find -lcryptopp (or -lcrypto++)
If you receive an error from collect2/ld stating cannot find -lcryptopp, the library is not installed or on path.
> g++ -o test test.cpp -lcryptopp .../i586-suse-linux/bin/ld: cannot find -lcryptopp collect2: ld returned 1 exit status
Verify the library is installed:
> whereis libcryptopp libcryptopp: /usr/lib/libcryptopp.a /usr/lib64/libcryptopp.a
If installed, try specifying the path with the -L option (below, change /usr/lib to the library location). (Also see GCC Options for Linking)
> g++ -o test test.cpp -L/usr/lib -lcryptopp
If the library is not installed and it cannot be found in the distribution, it might be named libcrypto++.a or libcrypto++.so (or vice-versa: libcryptopp.a or libcryptopp.so):
> g++ -o test test.cpp -lcrypto++
Undefined Reference to WSA Sockets
If you encounter link errors relating to sockets such as the following, you might need to add -lws2_32 to the link command. See trungantran's comments on Compile Error in socketft.cpp.
undefined reference to '_WSAEnumNetworkEvents@12' undefined reference to '_WSAEventSelect@12' undefined reference to '_WSAGetOverlappedResult@20' undefined reference to '_WSAGetOverlappedResult@20' undefined reference to '_WSARecv@28' undefined reference to '_WSASend@28'
Undefined Reference to pthread
If you encounter link errors relating to pthreads such as "undefined reference to pthread_key_create" when creating libcryptopp.so or cryptest.exe, add -pthread to the LDFLAGS (encountered on OpenBSD 4.8/4.9).
./libcryptopp.so: undefined reference to `pthread_getspecific' ./libcryptopp.so: undefined reference to `pthread_key_delete' ./libcryptopp.so: undefined reference to `pthread_key_create' ./libcryptopp.so: undefined reference to `pthread_setspecific'
If you encounter link errors relating to pthreads such as "undefined reference to pthread_key_create" when linking against a shared object, you most likely did not link against the pthread library. See Eugene Zolenko's comments on the Crypto++ user group.
/usr/lib/gcc/i486-linux-gnu/4.3.2/../../../../lib/libcryptopp.so: undefined reference to `pthread_key_create' /usr/lib/gcc/i486-linux-gnu/4.3.2/../../../../lib/libcryptopp.so: undefined reference to `pthread_getspecific' /usr/lib/gcc/i486-linux-gnu/4.3.2/../../../../lib/libcryptopp.so: undefined reference to `pthread_key_delete' /usr/lib/gcc/i486-linux-gnu/4.3.2/../../../../lib/libcryptopp.so: undefined reference to `pthread_setspecific'
Try including the pthread library:
> g++ -o test test.cpp -lcryptopp -lpthread
File number X already allocated
If using precompiled headers and you get a message similar to "file number 2 already allocated", see Including a precompiled header from another header causes invalid assembly to be generated. The take away: upgrade to GCC 4.5.
No such instruction: pclmulqdq
pclmulqdq is part of Intel AVX. According to Intel Software Development Emulator, "GCC 4.4 includes support for these [AESNI and PCLMULQDQ] instructions". H.J. Lu's patch was submitted in 2008 and can be found at PATCH: Enable Intel AES/CLMUL.
cpu.h:53:no such instruction: `pclmulqdq $16, -64(%rbp),%xmm0' cpu.h:53:no such instruction: `pclmulqdq $0, -192(%rbp),%xmm0' cpu.h:53:no such instruction: `pclmulqdq $0, -80(%rbp),%xmm0' cpu.h:53:no such instruction: `pclmulqdq $16, -112(%rbp),%xmm0' cpu.h:53:no such instruction: `pclmulqdq $1, -144(%rbp),%xmm1' ...
According to X86 Built-in Functions, GCC requires the following to generate the instruction:
The following built-in function is available when -mpclmul is used. v2di __builtin_ia32_pclmulqdq128 (v2di, v2di, const int) Generates the pclmulqdq machine instruction.
If your processor does not support the instruction, or you don't want to generate AESNI and PCLMULQDQ instructions, define CRYPTOPP_DISABLE_AESNI
.
Debugging
If you attempt to debug a program linked to libcryptopp.a (or libcryptopp.so) and you cannot list your source file:
> (gdb) list main No line number known for main.
Verify that you have compiled with debugging information (the -g option):
> g++ -g -ggdb test.cpp -o test -lcryptopp
If you are using a distribution's library, make sure you have installed the development library and the debug symbols:
> # Debian, Ubuntu, and other Debian derivatives > apt-get install libcryptopp-dev libcryptopp-dbg
$ # Fedora and other RPM based systems $ yum install cryptopp cryptopp-devel cryptopp-develdebug
With debug symbols present, listing and stepping should be available:
(gdb) list 5 #include "cryptopp/osrng.h" 6 #include "cryptopp/secblock.h" 7 using CryptoPP::AutoSeededRandomPool; 8 using CryptoPP::SecByteBlock; 9 10 int main( int, char** ) { 11 12 AutoSeededRandomPool prng; 13 SecByteBlock block(16); 14 15 prng.GenerateBlock(block, block.size()); 16 17 return 0; 18 }
Downloads
Cryptopp-SO-Test.zip - test harness with multiple threads that calls one of four [test] shared objects (each is distinct). The four [test] shared objects each loads the libcryptopp.so shared object. See Note for Distribution Packagers above.