在native层 使用openssl

1.官方文档  

官网  https://www.openssl.org/
Compilation and Installation https://wiki.openssl.org/index.php/Compilation_and_Installation
android building  https://wiki.openssl.org/index.php/Android
Configuration "packages" https://wiki.openssl.org/index.php/Configuration_%22packages%22
API

https://wiki.openssl.org/index.php/Libcrypto_API

https://wiki.openssl.org/index.php/Documentation_Index

https://wiki.openssl.org/index.php/OpenSSL_1.1.0_Changes

Diffie-Hellman parameters https://wiki.openssl.org/index.php/Diffie-Hellman_parameters
Libssl API apt-get install libssl-dev
Examples https://wiki.openssl.org/index.php/Category:Examples

解压源码包后,仔细阅读  

  INSTALL.md 和 NOTES-ANDROID.md  这两个文件。

2.编译

依赖工具 :

  • AR
  • BUILDFILE
  • CC
  • CROSS_COMPILE
  • NM
  • OPENSSL_LOCAL_CONFIG_DIR
  • PERL
  • HASHBANGPERL
  • RC
  • RANLIB
  • WINDRES

2.1 配置选项

查看支持的系统、平台.

$ ./Configure LIST 

如下:

...
android-arm
android-arm64
android-armeabi
android-mips
android-mips64
android-x86
android-x86_64
android64
android64-aarch64
android64-mips64
android64-x86_64
bsdi-elf-gcc
cc
darwin-i386
darwin-i386-cc
darwin-ppc
darwin-ppc-cc
darwin64-arm64
darwin64-arm64-cc
darwin64-ppc
darwin64-ppc-cc
darwin64-x86_64
darwin64-x86_64-cc
...

设置环境,新建setenv.sh,然后刷新。

export ANDROID_NDK_ROOT=~/android/sdk/ndk/22.1.7171670
export PATH=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin:$ANDROID_NDK_ROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin:$ANDROID_NDK_ROOT/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin:$PATH

配置参数、特性等

./Configure android-x86_64 -D__ANDROID_API__=30

还有另外两个版本

  • android-arm
  • android-arm64

可配置的参选项很多,如:

  • no-deprecated
  • enable-fips
  • 等等,详见:INSTALL.md

  其中:no-开头的表示默认已打开,使用no-表示关闭。enable-开头的表示默认关闭,使用enable-时打开。

查看已配置选项

$configdata.pm --dump 

2.2 编译

$make -j8 V=1

This will build the OpenSSL libraries (`libcrypto.a` and `libssl.a` on Unix, corresponding on other platforms) and the OpenSSL binary (`openssl`). 

The libraries will be built in the top-level directory, and the binary will be in the `apps/` subdirectory.

编译完后可以测试下

$make test

2.3 生成的文件

在根目录下:

3.几个注意事项

3.1 关于多线程

  For some systems, the OpenSSL `Configure` script knows what compiler options are needed to generate a library that is suitable for multi-threaded applications.  On these systems, support for multi-threading is enabled by default; use the `no-threads` option to disable (this should never be necessary).

  On other systems, to enable support for multi-threading, you will have to specify at least two options: `threads`, and a system-dependent option. (The latter is `-D_REENTRANT` on various systems.)  The default in this case, obviously, is not to include support for multi-threading (but you can still use `no-threads` to suppress an annoying warning message from the `Configure` script.)

  OpenSSL provides built-in support for two threading models: pthreads (found on most UNIX/Linux systems), and Windows threads.  No other threading models are supported.  If your platform does not provide pthreads or Windows threads then you should use `Configure` with the `no-threads` option.

  For pthreads, all locks are non-recursive. In addition, in a debug build, the mutex attribute `PTHREAD_MUTEX_ERRORCHECK` is used. If this is not available on your platform, you might have to add `-DOPENSSL_NO_MUTEX_ERRORCHECK` to your `Configure` invocation. (On Linux `PTHREAD_MUTEX_ERRORCHECK` is an enum value, so a built-in ifdef test cannot be used.)

3.2 so库

  For most systems the OpenSSL `Configure` script knows what is needed to build shared libraries for libcrypto and libssl.  On these systems the shared libraries will be created by default.  This can be suppressed and only static libraries created by using the `no-shared` option.  On systems where OpenSSL does not know how to build shared libraries the `no-shared` option will be forced and only static libraries will be created.

  Shared libraries are named a little differently on different platforms. One way or another, they all have the major OpenSSL version number as part of the file name, i.e.  for OpenSSL 1.1.x, `1.1` is somehow part of the name.

  On most POSIX platforms, shared libraries are named `libcrypto.so.1.1` and `libssl.so.1.1`.

  on Cygwin, shared libraries are named `cygcrypto-1.1.dll` and `cygssl-1.1.dll` with import libraries `libcrypto.dll.a` and `libssl.dll.a`.

  On Windows build with MSVC or using MingW, shared libraries are named `libcrypto-1_1.dll` and `libssl-1_1.dll` for 32-bit Windows, `libcrypto-1_1-x64.dll` and `libssl-1_1-x64.dll` for 64-bit x86_64 Windows, and `libcrypto-1_1-ia64.dll` and `libssl-1_1-ia64.dll` for IA64 Windows. With MSVC, the import libraries are named `libcrypto.lib` and `libssl.lib`, while with MingW, they are named `libcrypto.dll.a` and `libssl.dll.a`.

  On VMS, shareable images (VMS speak for shared libraries) are named `ossl$libcrypto0101_shr.exe` and `ossl$libssl0101_shr.exe`.  However, when OpenSSL is specifically built for 32-bit pointers, the shareable images are named `ossl$libcrypto0101_shr32.exe` and `ossl$libssl0101_shr32.exe` instead, and when built for 64-bit pointers, they are named `ossl$libcrypto0101_shr64.exe` and `ossl$libssl0101_shr64.exe`.

3.3 随机数

  Availability of cryptographically secure random numbers is required for secret key generation. OpenSSL provides several options to seed the internal CSPRNG. If not properly seeded, the internal CSPRNG will refuse to deliver random bytes and a "PRNG not seeded error" will occur.

  The seeding method can be configured using the `--with-rand-seed` option, which can be used to specify a comma separated list of seed methods. However, in most cases OpenSSL will choose a suitable default method, so it is not necessary to explicitly provide this option.  Note also that not all methods are available on all platforms.  The FIPS provider will silently ignore seed sources that were not validated.

  I) On operating systems which provide a suitable randomness source (in form  of a system call or system device), OpenSSL will use the optimal available  method to seed the CSPRNG from the operating system's randomness sources.  This corresponds to the option `--with-rand-seed=os`.

  II) On systems without such a suitable randomness source, automatic seeding and reseeding is disabled (`--with-rand-seed=none`) and it may be necessary to install additional support software to obtain a random seed and reseed the CSPRNG manually.  Please check out the manual pages for `RAND_add()`, `RAND_bytes()`, `RAND_egd()`, and the FAQ for more information.

4.使用libssl

  • 可以把libssl复制到ndk中使用
  • 也可以在项目jni源码中使用
  • 二选一,混用容易出错。

4.1 复制libssl到ndk中

把生成的 libssl.a 和 libcrypto.a 复制到  android/sdk/ndk/22.1.7171670/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/ 下的每个cpu架构根目录下。

  

4.2 复制头文件

  把openssl include目录下的 crypto internal openssl 3个目录复制到 android/sdk/ndk/22.1.7171670/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/ 目录下

  

5.使用

  如libcurl 等。

static CURLcode sslctx_function(CURL *curl, void *sslctx, void *parm)
{
  CURLcode rv = CURLE_ABORTED_BY_CALLBACK;

  /** This example uses two (fake) certificates **/
  static const char mypem[] =
    "-----BEGIN CERTIFICATE-----\n"
    "MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UE\n"
    "AwwJQUNDVlJBSVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQsw\n"
    "CQYDVQQGEwJFUzAeFw0xMTA1MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQ\n"
    "BgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwHUEtJQUNDVjENMAsGA1UECgwEQUND\n"
    "VjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCb\n"
    "qau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gMjmoY\n"
    "HtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWo\n"
    "G2ioPej0RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpA\n"
    "0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDGWuzndN9wrqODJerWx5eH\n"
    "k6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs78yM2x/47\n"
    "JyCpZET/LtZ1qmxNYEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+m\n"
    "AM/EKXMRNt6GGT6d7hmKG9Ww7Y49nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepD\n"
    "vV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJTS+xJlsndQAJxGJ3KQhfnlms\n"
    "tn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3sCPdK6jT2iWH\n"
    "7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h\n"
    "I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szA\n"
    "h1xA2syVP1XgNce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xF\n"
    "d3+YJ5oyXSrjhO7FmGYvliAd3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2H\n"
    "pPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3pEfbRD0tVNEYqi4Y7\n"
    "-----END CERTIFICATE-----\n"
    "-----BEGIN CERTIFICATE-----\n"
    "MIIFtTCCA52gAwIBAgIIYY3HhjsBggUwDQYJKoZIhvcNAQEFBQAwRDEWMBQGA1UE\n"
    "AwwNQUNFRElDT00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00x\n"
    "CzAJBgNVBAYTAkVTMB4XDTA4MDQxODE2MjQyMloXDTI4MDQxMzE2MjQyMlowRDEW\n"
    "MBQGA1UEAwwNQUNFRElDT00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZF\n"
    "RElDT00xCzAJBgNVBAYTAkVTMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC\n"
    "AgEA/5KV4WgGdrQsyFhIyv2AVClVYyT/kGWbEHV7w2rbYgIB8hiGtXxaOLHkWLn7\n"
    "09gtn70yN78sFW2+tfQh0hOR2QetAQXW8713zl9CgQr5auODAKgrLlUTY4HKRxx7\n"
    "XBZXehuDYAQ6PmXDzQHe3qTWDLqO3tkE7hdWIpuPY/1NFgu3e3eM+SW10W2ZEi5P\n"
    "gvoFNTPhNahXwOf9jU8/kzJPeGYDdwdY6ZXIfj7QeQCM8htRM5u8lOk6e25SLTKe\n"
    "I6RF+7YuE7CLGLHdztUdp0J/Vb77W7tH1PwkzQSulgUV1qzOMPPKC8W64iLgpq0i\n"
    "5ALudBF/TP94HTXa5gI06xgSYXcGCRZj6hitoocf8seACQl1ThCojz2GuHURwCRi\n"
    "ipZ7SkXp7FnFvmuD5uHorLUwHv4FB4D54SMNUI8FmP8sX+g7tq3PgbUhh8oIKiMn\n"
    "MCArz+2UW6yyetLHKKGKC5tNSixthT8Jcjxn4tncB7rrZXtaAWPWkFtPF2Y9fwsZ\n"
    "o5NjEFIqnxQWWOLcpfShFosOkYuByptZ+thrkQdlVV9SH686+5DdaaVbnG0OLLb6\n"
    "zqylfDJKZ0DcMDQj3dcEI2bw/FWAp/tmGYI1Z2JwOV5vx+qQQEQIHriy1tvuWacN\n"
    "GHk0vFQYXlPKNFHtRQrmjseCNj6nOGOpMCwXEGCSn1WHElkQwg9naRHMTh5+Spqt\n"
    "r0CodaxWkHS4oJyleW/c6RrIaQXpuvoDs3zk4E7Czp3otkYNbn5XOmeUwssfnHdK\n"
    "Z05phkOTOPu220+DkdRgfks+KzgHVZhepA==\n"
    "-----END CERTIFICATE-----\n";

  BIO *cbio = BIO_new_mem_buf(mypem, sizeof(mypem));
  X509_STORE  *cts = SSL_CTX_get_cert_store((SSL_CTX *)sslctx);
  int i;
  STACK_OF(X509_INFO) *inf;
  (void)curl;
  (void)parm;

  if(!cts || !cbio) {
    return rv;
  }

  inf = PEM_X509_INFO_read_bio(cbio, NULL, NULL, NULL);

  if(!inf) {
    BIO_free(cbio);
    return rv;
  }

  for(i = 0; i < sk_X509_INFO_num(inf); i++) {
    X509_INFO *itmp = sk_X509_INFO_value(inf, i);
    if(itmp->x509) {
      X509_STORE_add_cert(cts, itmp->x509);
    }
    if(itmp->crl) {
      X509_STORE_add_crl(cts, itmp->crl);
    }
  }

  sk_X509_INFO_pop_free(inf, X509_INFO_free);
  BIO_free(cbio);

  rv = CURLE_OK;
  return rv;
}

 

posted @ 2021-07-25 22:34  f9q  阅读(878)  评论(0编辑  收藏  举报