资讯专栏INFORMATION COLUMN

在Android NDK中使用OpenSSL

王岩威 / 1201人阅读

摘要:从开始,要求不要使用系统的,请见。本文将以调用中的算法为例,介绍如何使用配置并在中使用。需要在文件中指定属性,指向的路径。所有的配置放置在块中。里指定了的版本,在中使用里已经内置了,但中并没有提供相应的库。

从 6.0 开始,Google 要求不要使用系统的 OpenSSL,请见:https://developer.android.com...。因此,请不要再使用本文介绍的方法,请自行交叉编译 OpenSSL 或者使用别人编译好的版本。
2017年3月注

由于Java较为容易被反编译,因此把一些重要代码放在so文件中成为了一个代价不太高的选择。虽然so文件依旧可以反编译,但对so进行逆向分析的门槛则要比分析Java字节码的门槛高出不少。很多安全相关的代码都依赖OpenSSL,然而网络上在NDK中使用OpenSSL的教程并不多见,经过一天的探索,我终于可以成功在NDK中调用OpenSSL了。本文将以调用OpenSSL中的HMAC算法为例,介绍如何使用Gradle配置NDK并在NDK中使用OpenSSL。

在Gradle中配置NDK

2015年7月,Google发布了新的Gradle插件,提供了对NDK的支持,从此,编写NDK程序不再需要编写Android.mk文件,也不再需要使用ndk-build脚本,只需要在Gradle中简单的配置一下,即可方便的编译程序了。

目前,新的插件仍处在beta版本,本文选用当前时间(2016年3月2日)最新的0.6.0-beta5作介绍。要获取最新的更新,请访问这里。

从传统的Android Gradle插件迁移到新的插件并不困难,只需要修改原有目录结构中的三个文件即可。以如下目录为例:

.
├── app/
│   ├── build.gradle
│   └── src/
├── build.gradle
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── local.properties
└── settings.gradle

需要修改的文件包括两个build.gradlegradle-wrapper.propertieslocal.properties文件。

分别来看对它们的修改:

每个版本的插件都只支持特定的Gradle版本,因此请务必对照上文给出的链接填写正确的版本。

./local.properties

需要在文件中指定ndk.dir属性,指向NDK的路径。

./gradle/wrapper/gradle-wrapper.properties

这个文件定义了Gradle的版本,这里需要使用gradle-2.10,因此需要把最后一行的版本替换掉。

./build.gradle

这里定义了构建时使用的插件,需要替换为com.android.tools.build:gradle-experimental:0.6.0-beta5

./app/build.gradle

这个文件变化较大,主要的变化包括:

插件名由原来的com.android.application变为com.android.model.application

所有的配置放置在model { }块中。

minSdkVersiontargetSdkVersion都需要配置它们的apiLevel属性。

下面是一个完整的示例:

apply plugin: "com.android.model.application"

model {
    android {
        compileSdkVersion 23
        buildToolsVersion "23.0.2"

        defaultConfig {
            applicationId "com.example.openssltest"
            minSdkVersion.apiLevel 14
            targetSdkVersion.apiLevel 23
            versionCode 1
            versionName "1.0"
        }

        ndk {
            moduleName = "openssl-jni"
            platformVersion = 14
            ldFlags.add("-lcrypto")
            abiFilters.add("armeabi-v7a")
        }
    }
}

dependencies {
    compile "com.android.support:appcompat-v7:23.1.1"
}

这个配置中,多出了ndk部分,下面就来解释一下这部分的配置:

moduleName决定了编译出来的库的名称,这个选项是必须的。

platformVersion指定了NDK的platform版本,这里使用14是因为minSdkVersion使用14。

ldFlags指定了链接时的参数,由于本例中只用到了HMAC算法,因此这里添加了对crypto,如果还需要TLS的支持,这里需要改为ldFlags.addAll(["-lcrypto", "-lssl"])

abiFilters里指定了abi的版本armeabi-v7a

在NDK中使用OpenSSL

Android里已经内置了OpenSSL,但NDK中并没有提供相应的库。只需要把OpenSSL的.so文件放在NDK中即可:

$adb pull /system/lib/libssl.so /myndk/platforms/android-14/arch-arm/usr/lib

$adb pull /system/lib/libcrypto.so /myndk/platforms/android-14/arch-arm/usr/lib

然后把OpenSSL的头文件放在 /myndk/platforms/android-14/arch-arm/usr/include 目录中即可。

编写代码请参考JNI的文档,下面给出一个调用HMAC-SHA256的实现:

#include 
#include 

#ifdef __cplusplus
extern "C" {
#endif
jbyteArray
Java_com_example_openssltest_MainActivity_hmacSha256(JNIEnv *env,
                                                     jobject obj,
                                                     jbyteArray content) {
  unsigned char key[] = {0x6B, 0x65, 0x79};

  unsigned int result_len;
  unsigned char result[EVP_MAX_MD_SIZE];

  // get data from java array
  jbyte *data = env->GetByteArrayElements(content, NULL);
  size_t dataLength = env->GetArrayLength(content);

  HMAC(EVP_sha256(),
       key, 3,
       (unsigned char *) data, dataLength,
       result, &result_len);

  // release the array
  env->ReleaseByteArrayElements(content, data, JNI_ABORT);

  // the return value
  jbyteArray return_val = env->NewByteArray(result_len);
  env->SetByteArrayRegion(return_val, 0, result_len, (jbyte *) result);
  return return_val;
}
#ifdef __cplusplus
}
#endif

在Java中调用也很容易,只需要引用build.gradle中指定的库即可:

public native byte[] hmacSha256(byte[] data);

static {
    System.loadLibrary("openssl-jni");
}
DEMO项目链接

https://github.com/terro/andr...

需要注意的是,这里只是一个简单的DEMO,不要直接在项目中保存密钥之类的信息。



原文链接:https://dangfan.me/zh-Hans/po...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/12627.html

相关文章

  • Andorid Studio NDK开发-使用NDK

    摘要:首先定义一个方法,该方法的目的是从中读取随机数对应的方法引入的使用的方法是的方法,能够读取随机数。这段代码的意思就是读取一个位的随机数,然后转换为的数组。 C语言是一个巨大的宝库,Android是一个以Linux为基础的开源操作系统,系统底层很多的实现都是基于C语言开发,比如图像处理,加密等。另一方面C语言的运行效率也比Java开发要高很多,因此为了高效率的运行有时候也会使用C语言开发...

    Leck1e 评论0 收藏0
  • Andorid Studio NDK开发-编译OpenSSL类库

    摘要:在上开发对于安全的需求越来越高,虽然出现过几次漏洞,但它仍然是在安全方面的使用最多的加密库之一。这篇文章主要写的是如何编译的类库。 OpenSSL是一个强大的开源安全套接字层密码库,它包含了主要的密码学算法,常用的密钥和证书封装管理以及SSL协议,并提供丰富的应用程序供测试或其他目的使用。在Android上开发对于安全的需求越来越高,虽然OpenSSL出现过几次漏洞,但它仍然是在安全方...

    yiliang 评论0 收藏0
  • Andorid Studio NDK开发-使用

    摘要:总而言之,会在开发的过程中会使用大量的库,系统自带的库,第三方库等。在中使用语言的库是非常便利的。这里引入的库为静态链接库,名称为指定库依赖动态链接库这里在中指定库的依赖为上面定义的类型为如果是动态链接库就是。 C语言是一个巨大的宝库,系统底层的很多的实现都是基于C语言实现的,比如图像处理,加密等。C语言的运行效率也是很高的,因此为了效率有时候也会引入第三方的C语言库。总而言之,会在N...

    Freeman 评论0 收藏0
  • Android NDK和OpenCV整合开发 (2) Android NDK

    摘要:详细的内容可以查看文件,这个文件可能并没有列出在中我们可以从下面的表格中看出它们对语言特性的支持程度从中我们可以看出很不错,所以一般会配置为。将传递到层解析出现了乱码使用自定义的将转换成的函数,内容如下 Android NDK 和 OpenCV 整合开发 (2) Android NDK 这节主要介绍的内容是Android NDK开发的核心内容和开发总结(包括很多常见问题的解决方案),...

    yangrd 评论0 收藏0
  • Android Studio NDK开发-环境配置

    摘要:开发环境配置全称。还提供了一份稳定的功能有限的头文件声明。以前使用做开发是件很麻烦的事情,特别是配置文件的编写。环境要求需要安装最新版的。会自动下载等开发工具。注对应环境变量的设置 Android Studio NDK开发-环境配置 NDK全称Native Development Kit。NDK是一系列Android开发工具的集合,NDK提供了一系列的工具,可以帮助开发者在Androi...

    anquan 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<