Android CMakeはOpenSSLベースのSHA(1-512)署名を簡単に実現

4343 ワード

セキュリティ暗号化C言語ライブラリOpenSSL、Androidでのサーバとクライアント間の署名検証やデータ暗号化通信など.
OpenSSLシリーズの記事:
一、Android CMakeは簡単にOpenSSLに基づくHmacSHA 1署名を実現する
二、Android CMakeは簡単にOpenSSLに基づくSHA(1-512)署名を実現する
三、Android CMakeは簡単にOpenSSLに基づくMD 5情報の要約&異或いは復号を実現する
四、Android CMakeは簡単にOpenSSLに基づくAESの復号化を実現する
五、Android CMakeは簡単にOpenSSLに基づくRSAの復号化を実現する
六、Android CMakeは簡単にOpenSSLに基づくRSA署名と検証を実現する
七、Retrofitの基礎の上でOpenSSLと結合してサーバーとクライアント間のデータ暗号化通信を実現する
SHA(1-512)シリーズのアルゴリズム紹介:
セキュリティハッシュアルゴリズム(Secure Hash Algorithm)は、デジタル署名規格(Digital Signature Standard DSS)で定義されたデジタル署名アルゴリズム(Digital Signature Algorithm DSA)に主に適用される.1、出力長固定.すなわち、出力長と入力長は関係なく2、不可逆である.すなわち、出力データから入力データ3が理論的に導出されず、入力データに敏感である.入力データの変化が極めて小さい場合、出力データも著しく変化する4、衝突防止.すなわち、異なるデータデータが同じ出力データを得る可能性は極めて低い.情報要約には上述の特徴があるため、一般的にデータの完全性を検証し、大きなファイルに対して要約演算を行い、その要約値を得るために用いられる.ネットワークまたは他のチャネルで転送した後、その要約値を検証することで、大きなファイル自体に変化があるかどうかを決定します.
暗号化アルゴリズムと要約アルゴリズムの違い
暗号化された暗号文は,対応する鍵を用いて復号でき,元のデータが得られ,要約は逆復号できない.暗号化後の暗号文の長さは不定であり,要約の長さは決定される.非対称暗号化は明文の長さに制限があり、要約は明文の長さに制限がない.
SHA(1-512)シリーズAPI紹介:
1、unsigned char *SHA1(const unsigned char *d, size_t n, unsigned char *md);

2、int SHA1_Init(SHA_CTX *c);
int SHA1_Update(SHA_CTX *c, const void *data, size_t len);
int SHA1_Final(unsigned char *md, SHA_CTX *c);

最初の関数の紹介:パラメータdはデータブロックの開始アドレスであり、nはデータブロックの長さであり、計算されたハッシュ値はパラメータmdが指すメモリに格納される.mdがNULLの場合、SHA 1関数は計算されたハッシュ値を関数内部の静的空間に格納し、関数戻り値によって返します.第2のAPIセットについては3つの関数からなることを示した.ざっと見ると、3つの関数がSHA 1関数を完成させる機能ではないかと感じるお客様もいます.どうして3つの関数を作るのですか.ほほほ、OpenSSLは明らかに十分な理由でこのようにしたのです.ポイントはSHA 1ですUpdateという関数は複数回呼び出され、計算されるハッシュ値のデータが重畳され、最終的にハッシュ値が生成されます.今でもその使用シーンを考えていない人もいるかもしれませんが、例を挙げてみましょう.例えば、ファイルサイズが6 GBの場合、32ビットのプログラムが4 GB以上のメモリスペースにアクセスできないことを知っています(プログラマが操作できるのは最大3 GBで、プログラム/データ/スタック/保護エリアなどが1 GB程度のスペースを占有することがあります).このとき、このファイルのハッシュ値をどのように計算しますか?SHA 1はきっとだめだ.このとき、私たちはN回に分けてこのファイルを読むことができて、毎回1 MBのデータを読んで、それからSHA 1_を呼び出しますUpdate関数はハッシュ値の計算を積算し、ファイルのすべてのデータを読み終わったらSHA 1_を呼び出します.Final関数を使用して、最終的なハッシュ値を取得します.ここでは文字列署名検証のみを行います.
具体的な実装:
Java_com_alley_openssl_util_JniUtils_encodeBySHA1(JNIEnv *env, jobject instance, jbyteArray src_) {
    jbyte *src = env->GetByteArrayElements(src_, NULL);
    jsize src_Len = env->GetArrayLength(src_);

    char buff[SHA_DIGEST_LENGTH];
    char hex[SHA_DIGEST_LENGTH * 2];
    unsigned char digest[SHA_DIGEST_LENGTH];

//    SHA1((unsigned char *)src, src_Len, digest);

    SHA_CTX ctx;
    SHA1_Init(&ctx);
    LOGI("SHA1->    SHA1    ");
    SHA1_Update(&ctx, src, src_Len);
    SHA1_Final(digest, &ctx);

    OPENSSL_cleanse(&ctx, sizeof(ctx));

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

    LOGI("SHA1-> jni      ");
    env->ReleaseByteArrayElements(src_, src, 0);

    return env->NewStringUTF(hex);
}

同様に、他のSHA要約アルゴリズムの実装プロセスは、コードを読んでください.アドレスは文末を参照してください.ここにSHA 512実装プロセスが貼られていて、何が起こっているのか一目でわかります.
JNIEXPORT jstring JNICALL
Java_com_alley_openssl_util_JniUtils_encodeBySHA512(JNIEnv *env, jobject instance, jbyteArray src_) {
    jbyte *src = env->GetByteArrayElements(src_, NULL);
    jsize src_Len = env->GetArrayLength(src_);

    char buff[SHA512_DIGEST_LENGTH];
    char hex[SHA512_DIGEST_LENGTH * 2];
    unsigned char digest[SHA512_DIGEST_LENGTH];

//    SHA512((unsigned char *)src, src_Len, digest);

    SHA512_CTX ctx;
    SHA512_Init(&ctx);
    LOGI("SHA512->    SHA256    ");
    SHA512_Update(&ctx, src, src_Len);
    SHA512_Final(digest, &ctx);

    OPENSSL_cleanse(&ctx, sizeof(ctx));

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

    LOGI("SHA512-> jni      ");
    env->ReleaseByteArrayElements(src_, src, 0);

    return env->NewStringUTF(hex);
}

計算結果は文字列形式でJavaレイヤに返され、テスト結果は正しい.コードをダウンロードして実行し、コンソールに「body」と入力すると、すべてのデバッグ情報が表示されます.star、fork、転載を歓迎します.
ソース:https://github.com/GitPhoenix/OpenSSL