Linux

From Crypto++ Wiki
Jump to navigation Jump to search

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:

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.

Shared Objects and Globals

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?).

Note for Shared Object Callers

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.

Linux Distributions Offering Crypto++
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

Examining program using dissy

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.