Android CMake輕松實(shí)現(xiàn)基于OpenSSL的HmacSHA1簽名

安全加密C語言庫OpenSSL阐滩,在Android中服務(wù)器和客戶端之間的簽名驗(yàn)證和數(shù)據(jù)加密通信等。

OpenSSL系列文章:

一砸西、Android CMake輕松實(shí)現(xiàn)基于OpenSSL的HmacSHA1簽名
二叶眉、Android CMake輕松實(shí)現(xiàn)基于OpenSSL的SHA(1-512)簽名
三、Android CMake輕松實(shí)現(xiàn)基于OpenSSL的MD5信息摘要&異或加解密
四芹枷、Android CMake輕松實(shí)現(xiàn)基于OpenSSL的AES加解密
五衅疙、Android CMake輕松實(shí)現(xiàn)基于OpenSSL的RSA加解密
六、Android CMake輕松實(shí)現(xiàn)基于OpenSSL的RSA簽名和驗(yàn)證
七鸳慈、在Retrofit的基礎(chǔ)上結(jié)合OpenSSL實(shí)現(xiàn)服務(wù)器和客戶端之間數(shù)據(jù)加密通信
最近有這么一個需求饱溢,要對接口進(jìn)行簽名驗(yàn)證以防止被刷。開始想到了在Java中實(shí)現(xiàn)HmacSHA1簽名走芋,但由于Java代碼較容易反編譯直接獲取秘鑰绩郎,而否定了這個方案。為了解決這個問題翁逞,把實(shí)現(xiàn)簽名的邏輯代碼用C/C++來編寫肋杖,編譯成xxx.so庫,大大提高了反編譯的門檻挖函,從而降低了被反編譯的風(fēng)險状植。

在C/C++中要實(shí)現(xiàn)HmacSHA1簽名,只有依賴一個很出名的C語言中常用的加解密庫OpenSSL。什么是OpenSSL請自行百度津畸,隨便搜都是一大堆振定。難點(diǎn)在于在Android中進(jìn)行Jni開發(fā),在C/C++文件中要調(diào)用第三方OpenSSL的xxx.so庫肉拓,那怎樣才能把OpenSSL的xxx.so庫引入我們的C/C++文件中呢后频?換句話說就是最終我們的C/C++文件會被編譯成一個.so庫,就叫l(wèi)ibsignature.so吧暖途!而這個庫又引用了第三方xxx.so庫卑惜。不過不用擔(dān)心,自從Android支持CMake后丧肴,一切都變得簡單了残揉。網(wǎng)絡(luò)上也有很多博客,也有很多代碼片段芋浮,但是對于初學(xué)者來說,根本不知道那是什么玩意兒壳快!所以我想寫細(xì)一點(diǎn)纸巷。

一:新建項(xiàng)目
如下圖勾選include C++ support,然后一路next眶痰,直到finish瘤旨。


新建NDK工程.png

二:編譯OpenSSL源碼得到.so庫
OpenSSL源碼:github上搜索關(guān)鍵字【OpenSSL for Android】下載并編譯,拷貝所有.so到app/alley/lib/目錄下竖伯,拷貝OpenSSL所有頭文件到app/alley/include/openssl/目錄下存哲。


alley文件目錄.png

三:gradle配置

#app目錄下build.gradle
apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "com.alley.openssl"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                cppFlags "-std=c++11 -frtti -fexceptions"
                //目標(biāo)平臺,若需要更多平臺的請自行配置
                abiFilters 'armeabi'
            }
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    sourceSets {
        main {
            //第三方.so庫路徑
            jniLibs.srcDirs = ['E:\\AndroidSpace\\OpenSSL\\app\\alley\\lib']
        }
    }
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.3.1'
    compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha8'
    testCompile 'junit:junit:4.12'
}

四:CMakeLists腳本
CMakeLists腳本語法請自行查閱

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)
#C++編譯
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")

#配置加載頭文件
include_directories(E:/AndroidSpace/OpenSSL/app/alley/include)

#動態(tài)方式加載
add_library(openssl SHARED IMPORTED )
add_library(ssl SHARED IMPORTED )
#引入第三方.so庫
set_target_properties(openssl PROPERTIES IMPORTED_LOCATION E:/AndroidSpace/OpenSSL/app/alley/lib/${ANDROID_ABI}/libcrypto.so)
set_target_properties(ssl PROPERTIES IMPORTED_LOCATION E:/AndroidSpace/OpenSSL/app/alley/lib/${ANDROID_ABI}/libssl.so)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
             signature

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             src/main/cpp/signature.cpp )

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
                       signature
                       openssl
                       ssl
                       android

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )

五:加解密
HmacSHA1算法得到簽名結(jié)果為十六進(jìn)制數(shù)七婴。在本項(xiàng)目中對其進(jìn)行Base64編碼祟偷,發(fā)現(xiàn)編碼結(jié)果為28位的,這和用Java代碼實(shí)現(xiàn)的完全不同(Java實(shí)現(xiàn)的是56位)打厘,在線base64編碼測試結(jié)果也為56位修肠。原因是什么呢?
待編碼數(shù)據(jù)是按照** %02x 格式輸出的值户盯,然后用這個值再次進(jìn)行base64編碼嵌施。在這里解釋一下 %02x:按照十六進(jìn)制進(jìn)行數(shù)據(jù)輸出,不足兩位莽鸭,則在之前補(bǔ)0吗伤,否則按實(shí)際數(shù)據(jù)輸出。 所以用到了sprintf(char *, const char *, ...)和strcat(char , const char )函數(shù)硫眨,這才是重點(diǎn)啊足淆,不太容易發(fā)現(xiàn)。在開發(fā)過程中注意C++函數(shù)名與native方法的關(guān)系。將最后編譯生成的libsignature.so拷貝你的項(xiàng)目中就可以使用了缸浦。秘鑰自己設(shè)定夕冲,注意不要泄露了。更多詳情請閱讀源碼裂逐。

#include <jni.h>
#include <string>
#include <Android/log.h>
#include <openssl/hmac.h>


#define TAG "JNI"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)

extern "C"
JNIEXPORT jbyteArray JNICALL
Java_com_alley_openssl_util_JniUtils_getSignature(JNIEnv *env, jobject instance, jbyteArray value_) {
    const char *key = "5fd6s4gs8f7s1dfv23sdf4ag65rg4arhb4fb1f54bgf5gbvf1534as";
    LOGI("HmacSHA1->準(zhǔn)備獲取待加密數(shù)據(jù)");
    jbyte *value = env->GetByteArrayElements(value_, NULL);
    LOGI("HmacSHA1->準(zhǔn)備計(jì)算待加密數(shù)據(jù)長度");
    size_t value_Len = env->GetArrayLength(value_);

    unsigned int result_len;
    unsigned char result[EVP_MAX_MD_SIZE];
    char buff[EVP_MAX_MD_SIZE];
    char hex[EVP_MAX_MD_SIZE];

    LOGI("HmacSHA1->準(zhǔn)備進(jìn)行加密計(jì)算");
    HMAC(EVP_sha1(), key, strlen(key), (unsigned char *) value, value_Len, result, &result_len);
    LOGI("HmacSHA1->加密計(jì)算結(jié)束");

    strcpy(hex, "");
    for (int i = 0; i != result_len; i++) {
        sprintf(buff, "%02x", result[i]);
        strcat(hex, buff);
    }
    LOGI("HmacSHA1->");
    LOGI("%s", hex);

    env->ReleaseByteArrayElements(value_, value, 0);
    LOGI("HmacSHA1->jni釋放數(shù)據(jù)結(jié)束");
    jbyteArray signature = env->NewByteArray(strlen(hex));
    env->SetByteArrayRegion(signature, 0, strlen(hex), (jbyte *) hex);
    LOGI("HmacSHA1->準(zhǔn)備以ByteArray格式返回數(shù)據(jù)");
    return signature;
}

六:測試
待簽名數(shù)據(jù):Android CMake輕松實(shí)現(xiàn)基于OpenSSL的HmacSHA1簽名
秘鑰:5fd6s4gs8f7s1dfv23sdf4ag65rg4arhb4fb1f54bgf5gbvf1534as
在線簽名校驗(yàn):http://tool.oschina.net/encrypt?type=2歹鱼,經(jīng)測試代碼簽名和在線簽名結(jié)果相同。

下載代碼運(yùn)行卜高,在控制臺中輸入“body”弥姻,將看到所有調(diào)試信息。歡迎star掺涛,fork庭敦,轉(zhuǎn)載。

源碼:https://github.com/GitPhoenix/OpenSSL

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末薪缆,一起剝皮案震驚了整個濱河市秧廉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌拣帽,老刑警劉巖疼电,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異减拭,居然都是意外死亡蔽豺,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門拧粪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來修陡,“玉大人,你說我怎么就攤上這事可霎∑茄唬” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵啥纸,是天一觀的道長号杏。 經(jīng)常有香客問我,道長斯棒,這世上最難降的妖魔是什么盾致? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮荣暮,結(jié)果婚禮上庭惜,老公的妹妹穿的比我還像新娘。我一直安慰自己穗酥,他們只是感情好护赊,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布惠遏。 她就那樣靜靜地躺著,像睡著了一般骏啰。 火紅的嫁衣襯著肌膚如雪节吮。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天判耕,我揣著相機(jī)與錄音透绩,去河邊找鬼。 笑死壁熄,一個胖子當(dāng)著我的面吹牛帚豪,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播草丧,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼狸臣,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了昌执?” 一聲冷哼從身側(cè)響起烛亦,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎懂拾,沒想到半個月后此洲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡委粉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了娶桦。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贾节。...
    茶點(diǎn)故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖衷畦,靈堂內(nèi)的尸體忽然破棺而出栗涂,到底是詐尸還是另有隱情,我是刑警寧澤祈争,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布斤程,位于F島的核電站,受9級特大地震影響菩混,放射性物質(zhì)發(fā)生泄漏忿墅。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一沮峡、第九天 我趴在偏房一處隱蔽的房頂上張望疚脐。 院中可真熱鬧,春花似錦邢疙、人聲如沸棍弄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽呼畸。三九已至痕支,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蛮原,已是汗流浹背卧须。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瞬痘,地道東北人故慈。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像框全,于是被迫代替她去往敵國和親察绷。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容