0%

GmSSL的编译和使用

简述

GmSSL是一个开源的密码工具箱,支持SM2/SM3/SM4/SM9/ZUC等国密(国家商用密码)算法、SM2国密数字证书及基于SM2证书的SSL/TLS安全通信协议,支持国密硬件密码设备,提供符合国密规范的编程接口与命令行工具,可以用于构建PKI/CA、安全通信、数据加密等符合国密标准的安全应用。
GmSSL项目是OpenSSL项目的分支,并与OpenSSL保持接口兼容。因此GmSSL可以替代应用中的OpenSSL组件,并使应用自动具备基于国密的安全能力。GmSSL项目采用对商业应用友好的类BSD开源许可证,开源且可以用于闭源的商业应用。
GmSSL项目由北京大学关志副研究员的密码学研究组开发维护,项目源码托管于GitHub。自2014年发布以来,GmSSL已经在多个项目和产品中获得部署与应用,并获得2015年度“一铭杯”中国Linux软件大赛二等奖(年度最高奖项)与开源中国密码类推荐项目。GmSSL项目的核心目标是通过开源的密码技术推动国内网络空间安全建设。

安装

编译环境参考OpenSSL的编译和使用

1
2
3
# 安装 目录 - yooking@ubuntu:~/Downloads/gmssl$
wget https://github.com/guanzhi/GmSSL/archive/master.zip
unzip master.zip

编译

  1. 生成Makefile文件

    ./config生成Makefile文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # 目录 - yooking@ubuntu:~/Downloads/gmssl/GmSSL-master$ 
    # 使用./执行config生成Makefile文件
    ./config
    # 报错,信息如下
    Operating system: x86_64-whatever-linux2
    "glob" is not exported by the File::Glob module
    Can't continue after import errors at ./Configure line 18.
    BEGIN failed--compilation aborted at ./Configure line 18.
    "glob" is not exported by the File::Glob module
    Can't continue after import errors at ./Configure line 18.
    BEGIN failed--compilation aborted at ./Configure line 18.
    This system (linux-x86_64) is not supported. See file INSTALL for details.

    打开Configure文件,修改line 18

    1
    2
    3
    4
    5
    gedit Configure
    #line 18原始内容如下
    use if $^O ne "VMS", 'File::Glob' => qw/glob/;
    #修改为
    use if $^O ne "VMS", 'File::Glob' => qw/:glob/;

    重新执行./config

    1
    2
    3
    4
    5
    ./config
    # 再次报错,信息如下
    Something wrong with this line:
    Program fragment delivered error ``"glob" is not exported by the File::Glob module
    at /home/yooking/Downloads/gmssl/GmSSL-master/test/build.info at ./Configure line 1644.

    修改对应文件test/build.info

    1
    2
    3
    4
    5
    gedit test/build.info
    # build.info文件中发现
    use if $^O ne "VMS", 'File::Glob' => qw/glob/;
    # 同样进行修改
    use if $^O ne "VMS", 'File::Glob' => qw/:glob/;

    再次执行./config即可生成Makefile文件

  2. 编写编译脚本(参考官方文档)(修改自Github开源项目

    下载开源项目,并根据提示进行了对应的修改,修改请看注释#No

    运行前先执行

    1
    2
    # 请使用你的NDK路径
    export ANDROID_NDK=/home/yooking/Public/android/android-sdk/ndk/android-ndk-r21d

    _shared.sh文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    #!/bin/bash

    TOOLS_ROOT=`pwd`

    #1 这里使用的 ndk是r21d r21d 不具备 mips 和mips64
    ARCHS=("android" "android-armeabi" "android64-aarch64" "android-x86" "android64")
    # "android-mips" "android-mips64"
    ABIS=("armeabi" "armeabi-v7a" "arm64-v8a" "x86" "x86_64" )
    # "mips" "mips64"
    # Default to API 21 for it is the minimum requirement for 64 bit archs.
    #2 编译64位需要使用21或以上Anddroid-Api
    ANDROID_API=${ANDROID_API:-21}
    NDK=${ANDROID_NDK}

    configure() {
    ARCH=$1; OUT=$2; CLANG=${3:-""};

    #3 记住这里,很占空间,github项目上并没有对这个进行删除,这里我们会在后续进行删除
    TOOLCHAIN_ROOT=${TOOLS_ROOT}/${OUT}-android-toolchain

    if [ "$ARCH" == "android" ]; then
    export ARCH_FLAGS="-mthumb"
    export ARCH_LINK=""
    export TOOL="arm-linux-androideabi"
    NDK_FLAGS="--arch=arm"
    elif [ "$ARCH" == "android-armeabi" ]; then
    export ARCH_FLAGS="-march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb -mfpu=neon"
    export ARCH_LINK="-march=armv7-a -Wl,--fix-cortex-a8"
    export TOOL="arm-linux-androideabi"
    NDK_FLAGS="--arch=arm"
    elif [ "$ARCH" == "android64-aarch64" ]; then
    export ARCH_FLAGS=""
    export ARCH_LINK=""
    export TOOL="aarch64-linux-android"
    NDK_FLAGS="--arch=arm64"
    elif [ "$ARCH" == "android-x86" ]; then
    export ARCH_FLAGS="-march=i686 -mtune=intel -msse3 -mfpmath=sse -m32"
    export ARCH_LINK=""
    export TOOL="i686-linux-android"
    NDK_FLAGS="--arch=x86"
    elif [ "$ARCH" == "android64" ]; then
    export ARCH_FLAGS="-march=x86-64 -msse4.2 -mpopcnt -m64 -mtune=intel"
    export ARCH_LINK=""
    export TOOL="x86_64-linux-android"
    NDK_FLAGS="--arch=x86_64"
    elif [ "$ARCH" == "android-mips" ]; then
    export ARCH_FLAGS=""
    export ARCH_LINK=""
    export TOOL="mipsel-linux-android"
    NDK_FLAGS="--arch=mips"
    elif [ "$ARCH" == "android-mips64" ]; then
    export ARCH="linux64-mips64"
    export ARCH_FLAGS=""
    export ARCH_LINK=""
    export TOOL="mips64el-linux-android"
    NDK_FLAGS="--arch=mips64"
    fi;

    [ -d ${TOOLCHAIN_ROOT} ] || python $NDK/build/tools/make_standalone_toolchain.py \
    --api ${ANDROID_API} \
    --stl libc++ \
    --install-dir=${TOOLCHAIN_ROOT} \
    $NDK_FLAGS

    export TOOLCHAIN_PATH=${TOOLCHAIN_ROOT}/bin
    export NDK_TOOLCHAIN_BASENAME=${TOOLCHAIN_PATH}/${TOOL}
    export SYSROOT=${TOOLCHAIN_ROOT}/sysroot
    export CROSS_SYSROOT=$SYSROOT
    if [ -z "${CLANG}" ]; then
    export CC=${NDK_TOOLCHAIN_BASENAME}-gcc
    export CXX=${NDK_TOOLCHAIN_BASENAME}-g++
    else
    export CC=${TOOLCHAIN_PATH}/clang
    export CXX=${TOOLCHAIN_PATH}/clang++
    fi;
    export LINK=${CXX}
    export LD=${NDK_TOOLCHAIN_BASENAME}-ld
    export AR=${NDK_TOOLCHAIN_BASENAME}-ar
    export RANLIB=${NDK_TOOLCHAIN_BASENAME}-ranlib
    export STRIP=${NDK_TOOLCHAIN_BASENAME}-strip
    export CPPFLAGS=${CPPFLAGS:-""}
    export LIBS=${LIBS:-""}
    export CFLAGS="${ARCH_FLAGS} -fpic -ffunction-sections -funwind-tables -fstack-protector -fno-strict-aliasing -finline-limit=64"
    export CXXFLAGS="${CFLAGS} -std=c++11 -frtti -fexceptions"
    export LDFLAGS="${ARCH_LINK}"
    echo "**********************************************"
    echo "use ANDROID_API=${ANDROID_API}"
    echo "use NDK=${NDK}"
    echo "export ARCH=${ARCH}"
    echo "export NDK_TOOLCHAIN_BASENAME=${NDK_TOOLCHAIN_BASENAME}"
    echo "export SYSROOT=${SYSROOT}"
    echo "export CC=${CC}"
    echo "export CXX=${CXX}"
    echo "export LINK=${LINK}"
    echo "export LD=${LD}"
    echo "export AR=${AR}"
    echo "export RANLIB=${RANLIB}"
    echo "export STRIP=${STRIP}"
    echo "export CPPFLAGS=${CPPFLAGS}"
    echo "export CFLAGS=${CFLAGS}"
    echo "export CXXFLAGS=${CXXFLAGS}"
    echo "export LDFLAGS=${LDFLAGS}"
    echo "export LIBS=${LIBS}"
    echo "**********************************************"
    }

    build-gmssl4android.sh文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    #!/bin/bash
    #
    # Copyright 2016 leenjewel
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    # http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.

    set -u

    source ./_shared.sh

    # Setup architectures, library name and other vars + cleanup from previous runs
    LIB_NAME="GmSSL-master"
    LIB_DEST_DIR=${TOOLS_ROOT}/libs
    [ -d ${LIB_DEST_DIR} ] && rm -rf ${LIB_DEST_DIR}

    #4 这里判断了master.zip压缩包是否存在,如果不存在则下载最新的包,这里建议修改为判断解压后的文件夹是否存在,如果不存在才去重新下载,原因后续解释,例如[-f "GmSSL-master"] || wget https://github.com/guanzhi/GmSSL/archive/master.zip;
    [ -f "master.zip" ] || wget https://github.com/guanzhi/GmSSL/archive/master.zip;
    # Unarchive library, then configure and make for specified architectures
    configure_make() {
    ARCH=$1; ABI=$2;
    rm -rf "${LIB_NAME}"

    #5 这里建议修改为
    #5 if[![-f "GmSSL-master"]];then
    #5 unzip -o "master.zip"
    #5 fi
    unzip -o "master.zip"
    pushd "${LIB_NAME}"

    configure $*

    #support openssl-1.0.x
    if [[ $LIB_NAME != "GmSSL-master" ]]; then
    if [[ $ARCH == "android-armeabi" ]]; then
    ARCH="android-armv7"
    elif [[ $ARCH == "android64" ]]; then
    ARCH="linux-x86_64 shared no-ssl2 no-ssl3 no-hw "
    elif [[ "$ARCH" == "android64-aarch64" ]]; then
    ARCH="android shared no-ssl2 no-ssl3 no-hw "
    fi
    fi

    echo "use android api:${ANDROID_API}"

    ./Configure $ARCH \
    --prefix=${LIB_DEST_DIR}/${ABI} \
    --with-zlib-include=$SYSROOT/usr/include \
    --with-zlib-lib=$SYSROOT/usr/lib \
    zlib \
    no-asm \
    no-shared \
    no-unit-test\
    no-serpent

    PATH=$TOOLCHAIN_PATH:$PATH

    if make -j4; then
    make install

    OUTPUT_ROOT=${TOOLS_ROOT}/../output/android/gmssl-${ABI}
    [ -d ${OUTPUT_ROOT}/include ] || mkdir -p ${OUTPUT_ROOT}/include
    cp -r ${LIB_DEST_DIR}/${ABI}/include/openssl ${OUTPUT_ROOT}/include

    [ -d ${OUTPUT_ROOT}/lib ] || mkdir -p ${OUTPUT_ROOT}/lib
    cp ${LIB_DEST_DIR}/${ABI}/lib/libcrypto.a ${OUTPUT_ROOT}/lib
    cp ${LIB_DEST_DIR}/${ABI}/lib/libssl.a ${OUTPUT_ROOT}/lib
    fi;
    popd

    }



    for ((i=0; i < ${#ARCHS[@]}; i++))
    do
    if [[ $# -eq 0 ]] || [[ "$1" == "${ARCHS[i]}" ]]; then
    # Do not build 64 bit arch if ANDROID_API is less than 21 which is
    # the minimum supported API level for 64 bit.
    [[ ${ANDROID_API} < 21 ]] && ( echo "${ABIS[i]}" | grep 64 > /dev/null ) && continue;
    configure_make "${ARCHS[i]}" "${ABIS[i]}"
    fi

    #6 每次循环体结束,删除后缀为 -android-toolchain的文件,防止占用存储空间过大
    rm -rf ${TOOLS_ROOT}/*-android-toolchain
    done

    这里解释下注释#4的理由:

    该Github开源项目已三年没有更新了,或许旧版本可以正常使用,但新版本中确实要修改`Configure`和`test/build.info`两个文件后才可以正常使用,因此在下载完毕master包后,需要对zip压缩包内的两个文件进行修改,后续解压后该代码才可正常执行。修改参考`1.生成Makefile文件`
    如果参照`#4`和`#5`的修改建议,则可以修改解压后的`GmSSL-master`内的对应文件。

引用

  1. 配置
    Android Studio - gradle:3.5.2
    ndk - android-ndk-r21d

  2. 新建一个Native C++项目

  3. 将脚本生成的.a文件放在app/libs/下(必须,否则会报错)

  4. 将CMakeLists.txt文件移动到app/

  5. 修改app/buidl.gradle

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    android {
    defaultConfig {
    externalNativeBuild {
    cmake {
    cppFlags "-frtti -fexceptions -lz"
    }
    ndk {
    abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
    }
    }
    }
    externalNativeBuild {
    cmake {
    path "CMakeLists.txt"
    }
    }
    }
  1. 修改CMakeLists.txt

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    # 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)

    # 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.
    native-lib

    # Sets the library as a shared library.
    SHARED

    # Provides a relative path to your source file(s).
    src/main/cpp/native-lib.cpp
    src/main/cpp/utils.cpp
    )

    #引用头文件目录
    include_directories( src/main/cpp/include/)
    include_directories(src/main/cpp)
    add_library(crypto STATIC IMPORTED)
    set_target_properties(crypto
    PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/libcrypto.a)

    # 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.
    native-lib
    crypto
    # Links the target library to the log library
    # included in the NDK.
    ${log-lib} )
  1. e_os.h文件和openssl文件夹移动到app/src/main/cpp/include

  2. crypto文件夹移动到app/src/main/cpp

使用

  1. utils.h

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #ifndef MYAPPLICATION2_UTILS_H
    #define MYAPPLICATION2_UTILS_H

    unsigned char *hex2bin(const char *data, int size, int *outlen);

    char *bin2hex(unsigned char *data, int size);

    int b64_op(const unsigned char *in, int in_len, char *out, int out_len, int op);

    /*存储文件*/
    int writeBufToFile(char *file, char *buf);
    /*读取文件*/
    int readBufFromFile(char *file, char *buf);

    int initEcKey(EC_KEY *ec_key,char * path);


    #endif //MYAPPLICATION2_UTILS_H
  2. utils.cpp

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    #include <openssl/bio.h>
    #include <openssl/evp.h>
    #include <fcntl.h>
    #include <e_os.h>
    #include <string>
    #include <openssl/ec.h>
    #include <crypto/ec/ec_lcl.h>
    #include "utils.h"


    unsigned char *hex2bin(const char *data, int size, int *outlen) {
    int i = 0;
    int len = 0;
    char char1 = '\0';
    char char2 = '\0';
    unsigned char value = 0;
    unsigned char *out = NULL;

    if (size % 2 != 0) {
    return NULL;
    }

    len = size / 2;
    out = (unsigned char *) malloc(len * sizeof(char) + 1);
    if (out == NULL) {
    return NULL;
    }

    while (i < len) {
    char1 = *data;
    if (char1 >= '0' && char1 <= '9') {
    value = (char1 - '0') << 4;
    } else if (char1 >= 'a' && char1 <= 'f') {
    value = (char1 - 'a' + 10) << 4;
    } else if (char1 >= 'A' && char1 <= 'F') {
    value = (char1 - 'A' + 10) << 4;
    } else {
    free(out);
    return NULL;
    }
    data++;

    char2 = *data;
    if (char2 >= '0' && char2 <= '9') {
    value |= char2 - '0';
    } else if (char2 >= 'a' && char2 <= 'f') {
    value |= char2 - 'a' + 10;
    } else if (char2 >= 'A' && char2 <= 'F') {
    value |= char2 - 'A' + 10;
    } else {
    free(out);
    return NULL;
    }

    data++;
    *(out + i++) = value;
    }
    *(out + i) = '\0';

    if (outlen != NULL) {
    *outlen = i;
    }

    return out;
    }

    char *bin2hex(unsigned char *data, int size) {
    int i = 0;
    int v = 0;
    char *p = NULL;
    char *buf = NULL;
    char base_char = 'A';

    buf = p = (char *) malloc(size * 2 + 1);
    for (i = 0; i < size; i++) {
    v = data[i] >> 4;
    *p++ = v < 10 ? v + '0' : v - 10 + base_char;

    v = data[i] & 0x0f;
    *p++ = v < 10 ? v + '0' : v - 10 + base_char;
    }

    *p = '\0';
    return buf;
    }

    int b64_op(const unsigned char *in, int in_len,
    char *out, int out_len, int op) {
    int ret = 0;
    BIO *b64 = BIO_new(BIO_f_base64());
    BIO *bio = BIO_new(BIO_s_mem());
    BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
    BIO_push(b64, bio);
    if (op == 0) {
    ret = BIO_write(b64, in, in_len);
    BIO_flush(b64);
    if (ret > 0) {
    ret = BIO_read(bio, out, out_len);
    }

    } else {
    ret = BIO_write(bio, in, in_len);
    BIO_flush(bio);
    if (ret) {
    ret = BIO_read(b64, out, out_len);
    }
    }
    BIO_free(b64);
    return ret;
    }

    int writeBufToFile(char *file, char *buf) {
    int fd = open(file, O_CREAT | O_RDWR, 0666);
    if (fd == -1)
    return -1;
    int offset = write(fd, buf, 1024);
    if (offset == 0)
    return -2;
    close(fd);
    return 0;
    }

    int readBufFromFile(char *file, char *buf) {
    int fd = open(file, O_CREAT | O_RDWR, 0666);
    if (fd == -1)
    return -1;
    int offset = read(fd, buf, 1024);
    if (offset == 0)
    return -2;
    close(fd);
    return 0;
    }
  3. native-lib.cpp

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469
    470
    471
    472
    473
    474
    475
    476
    477
    478
    479
    480
    481
    482
    483
    484
    485
    486
    487
    488
    489
    490
    491
    492
    493
    494
    495
    496
    497
    498
    499
    500
    501
    502
    503
    504
    505
    506
    507
    508
    509
    510
    511
    512
    513
    514
    515
    516
    517
    518
    519
    520
    521
    522
    523
    524
    525
    526
    527
    528
    529
    530
    531
    532
    533
    534
    535
    536
    537
    538
    539
    540
    541
    542
    543
    544
    545
    546
    547
    548
    549
    550
    551
    552
    553
    554
    555
    556
    557
    558
    559
    560
    561
    562
    563
    564
    565
    566
    567
    568
    569
    570
    571
    572
    573
    574
    575
    576
    577
    578
    579
    580
    581
    582
    583
    584
    585
    586
    587
    588
    589
    590
    591
    592
    593
    594
    595
    596
    597
    598
    599
    600
    601
    602
    603
    604
    605
    606
    607
    608
    609
    610
    611
    612
    613
    614
    615
    616
    617
    618
    619
    620
    621
    622
    623
    624
    625
    626
    627
    628
    629
    630
    631
    632
    633
    634
    635
    636
    637
    638
    639
    640
    641
    642
    643
    644
    645
    646
    647
    648
    649
    650
    651
    652
    653
    654
    655
    656
    657
    658
    659
    660
    661
    662
    663
    664
    665
    666
    667
    668
    669
    670
    671
    672
    673
    674
    675
    676
    677
    678
    679
    680
    681
    682
    683
    684
    685
    686
    687
    688
    689
    690
    #include <jni.h>
    #include <string>
    #include <malloc.h>
    #include <openssl/ec.h>
    #include <openssl/evp.h>
    #include <openssl/sm2.h>
    #include <openssl/sms4.h>
    #include <crypto/ec/ec_lcl.h>
    #include <openssl/aes.h>
    #include <crypto/sm2/sm2_lcl.h>
    #include "utils.h"
    #include <syslog.h>
    #include <openssl/pem.h>

    using std::string;

    char *path;

    //获取sm2的密钥
    EC_KEY *getEcKey() {
    std::string p1 = path;
    p1.append("/private");

    std::string p2 = path;
    p2.append("/public");

    char *privateChar = (char *) malloc(1024);
    memset(privateChar, 0, 1024);
    readBufFromFile((char *) p1.c_str(), privateChar);

    char *publicChar = (char *) malloc(1024);
    memset(publicChar, 0, 1024);
    readBufFromFile((char *) p2.c_str(), publicChar);

    EC_KEY *ec_key;
    ec_key = EC_KEY_new_by_curve_name(NID_sm2p256v1);
    BN_CTX *ctx1 = BN_CTX_new();
    EC_POINT *pubkey_point = EC_POINT_hex2point(ec_key->group, publicChar, NULL, ctx1);
    int iret = EC_KEY_set_public_key(ec_key, pubkey_point);
    BIGNUM *bn_prikey = BN_new();
    iret = BN_hex2bn(&bn_prikey, privateChar);
    iret = EC_KEY_set_private_key(ec_key, bn_prikey);
    p1.clear();
    p2.clear();
    free(publicChar);
    free(privateChar);
    BN_free(bn_prikey);
    EC_POINT_free(pubkey_point);
    return ec_key;
    }

    extern "C"
    JNIEXPORT jbyteArray JNICALL
    Java_com_yooking_gmssldemo_MainActivity_aesEnc(JNIEnv *env,
    jobject instance,
    jbyteArray in_,
    jint length,
    jbyteArray key_) {
    jbyte *in = env->GetByteArrayElements(in_, NULL);
    jbyte *key = env->GetByteArrayElements(key_, NULL);

    int pading = AES_BLOCK_SIZE - length % AES_BLOCK_SIZE;
    int block = length / AES_BLOCK_SIZE;
    int endLen = AES_BLOCK_SIZE - pading;

    unsigned char *p = (unsigned char *) malloc(AES_BLOCK_SIZE + 1);
    memset(p, 0, AES_BLOCK_SIZE + 1);
    memset(p + endLen, pading, (size_t) pading);
    memcpy(p, in + block * AES_BLOCK_SIZE, (size_t) endLen);

    AES_KEY aes_key;
    AES_set_encrypt_key((const unsigned char *) key, 16 * 8, &aes_key);

    unsigned char *out = (unsigned char *) malloc((size_t) (length + pading + 1));
    memset(out, 0, (size_t) (length + pading + 1));

    for (int i = 0; i < block; i++) {
    AES_encrypt((const unsigned char *) (in + (i * AES_BLOCK_SIZE)),
    out + i * AES_BLOCK_SIZE,
    &aes_key);
    }
    AES_encrypt(p, out + block * AES_BLOCK_SIZE, &aes_key);

    jbyteArray array = env->NewByteArray(length + pading);
    env->SetByteArrayRegion(array, 0, length + pading, (const jbyte *) out);

    free(p);
    free(out);

    env->ReleaseByteArrayElements(in_, in, 0);
    env->ReleaseByteArrayElements(key_, key, 0);

    return array;
    }

    extern "C"
    JNIEXPORT jbyteArray JNICALL
    Java_com_yooking_gmssldemo_MainActivity_aesDec(JNIEnv *env,
    jobject instance,
    jbyteArray in_,
    jint length,
    jbyteArray key_) {
    jbyte *in = env->GetByteArrayElements(in_, NULL);
    jbyte *key = env->GetByteArrayElements(key_, NULL);

    AES_KEY aes_key;
    AES_set_decrypt_key((const unsigned char *) key, 16 * 8, &aes_key);

    unsigned char *out = (unsigned char *) malloc(length);
    memset(out, 0, length);

    for (int i = 0; i < length / 16; i++) {
    AES_decrypt((const unsigned char *) (in + (i * AES_BLOCK_SIZE)),
    out + i * AES_BLOCK_SIZE,
    &aes_key);
    }
    //去补位
    int padinglen = out[length - 1];
    memset(out + length - padinglen, 0, padinglen);

    jbyteArray array = env->NewByteArray(length - padinglen);
    env->SetByteArrayRegion(array, 0, length - padinglen, (const jbyte *) out);

    free(out);
    env->ReleaseByteArrayElements(in_, in, 0);
    env->ReleaseByteArrayElements(key_, key, 0);

    return array;
    }

    extern "C"
    JNIEXPORT jbyteArray JNICALL
    Java_com_yooking_gmssldemo_MainActivity_sha1(JNIEnv *env,
    jobject instance,
    jbyteArray in_,
    jint length) {
    jbyte *in = env->GetByteArrayElements(in_, NULL);

    unsigned char *sha1Msg = (unsigned char *) malloc(SHA_DIGEST_LENGTH + 1);
    memset(sha1Msg, 0, SHA_DIGEST_LENGTH + 1);

    SHA1((const unsigned char *) in, length, sha1Msg);

    jbyteArray array = env->NewByteArray(SHA_DIGEST_LENGTH);
    env->SetByteArrayRegion(array, 0, SHA_DIGEST_LENGTH, (const jbyte *) sha1Msg);

    free(sha1Msg);
    env->ReleaseByteArrayElements(in_, in, 0);

    return array;
    }

    extern "C"
    JNIEXPORT jint JNICALL
    Java_com_yooking_gmssldemo_MainActivity_genSM2KeyPairs(JNIEnv *env,
    jobject instance,
    jstring path_) {

    const char *p = env->GetStringUTFChars(path_, JNI_FALSE);
    int pLen = env->GetStringUTFLength(path_);

    path = (char *) malloc(pLen + 1);
    memset(path, 0, pLen + 1);
    memcpy(path, p, pLen);

    std::string p1 = path;
    p1.append("/private");

    std::string p2 = path;
    p2.append("/public");

    EC_KEY *ec_key = EC_KEY_new();
    ec_key = EC_KEY_new_by_curve_name(NID_sm2p256v1);
    EC_KEY_generate_key(ec_key);
    const EC_POINT *point = EC_KEY_get0_public_key(ec_key);
    char *publicChar = EC_POINT_point2hex(EC_KEY_get0_group(ec_key),
    point,
    POINT_CONVERSION_UNCOMPRESSED,
    BN_CTX_new());
    const BIGNUM *privateKey = EC_KEY_get0_private_key(ec_key);
    char *privateChar = BN_bn2hex(privateKey);

    int iRet = writeBufToFile((char *) p1.c_str(), privateChar);
    iRet = writeBufToFile((char *) p2.c_str(), publicChar);

    EC_KEY_free(ec_key);
    return 0;
    }

    extern "C"
    JNIEXPORT jbyteArray JNICALL
    Java_com_yooking_gmssldemo_MainActivity_sm3(JNIEnv *env,
    jobject instance,
    jbyteArray in_,
    jint length) {
    jbyte *in = env->GetByteArrayElements(in_, NULL);

    unsigned char *sm3Msg = (unsigned char *) malloc(SM3_DIGEST_LENGTH + 1);
    memset(sm3Msg, 0, SM3_DIGEST_LENGTH + 1);

    sm3((const unsigned char *) in, length, sm3Msg);

    jbyteArray array = env->NewByteArray(SM3_DIGEST_LENGTH);
    env->SetByteArrayRegion(array, 0, SM3_DIGEST_LENGTH, (const jbyte *) sm3Msg);

    free(sm3Msg);
    env->ReleaseByteArrayElements(in_, in, 0);

    return array;
    }



    extern "C"
    JNIEXPORT jbyteArray JNICALL
    Java_com_yooking_gmssldemo_MainActivity_sm4Enc(JNIEnv *env,
    jobject instance,
    jbyteArray in_,
    jint length,
    jbyteArray key_) {
    jbyte *in = env->GetByteArrayElements(in_, NULL);
    jbyte *key = env->GetByteArrayElements(key_, NULL);

    int pading = SMS4_KEY_LENGTH - length % SMS4_KEY_LENGTH;
    int block = length / SMS4_KEY_LENGTH;
    int endLen = SMS4_KEY_LENGTH - pading;

    unsigned char *p = (unsigned char *) malloc(SMS4_KEY_LENGTH + 1);
    memset(p, 0, SMS4_KEY_LENGTH + 1);
    memset(p + endLen, pading, (size_t) pading);
    memcpy(p, in + block * SMS4_KEY_LENGTH, (size_t) endLen);

    sms4_key_t sms4EncKey;
    sms4_set_encrypt_key(&sms4EncKey, (const unsigned char *) key);

    unsigned char *out = (unsigned char *) malloc((size_t) (length + pading + 1));
    memset(out, 0, (size_t) (length + pading + 1));

    for (int i = 0; i < block; i++) {
    sms4_encrypt((const unsigned char *) (in + (i * 16)), out + i * 16, &sms4EncKey);
    }
    sms4_encrypt(p, out + block * 16, &sms4EncKey);

    jbyteArray array = env->NewByteArray(length + pading);
    env->SetByteArrayRegion(array, 0, length + pading, (const jbyte *) out);

    free(p);
    free(out);
    env->ReleaseByteArrayElements(in_, in, 0);
    env->ReleaseByteArrayElements(key_, key, 0);

    return array;
    }

    extern "C"
    JNIEXPORT jbyteArray JNICALL
    Java_com_yooking_gmssldemo_MainActivity_sm4Dec(JNIEnv *env,
    jobject instance,
    jbyteArray in_,
    jint length,
    jbyteArray key_) {
    jbyte *in = env->GetByteArrayElements(in_, NULL);
    jbyte *key = env->GetByteArrayElements(key_, NULL);

    sms4_key_t sms4DecKey;
    sms4_set_decrypt_key(&sms4DecKey, (const unsigned char *) key);

    unsigned char *out = (unsigned char *) malloc(length);
    memset(out, 0, length);

    for (int i = 0; i < length / 16; i++) {
    sms4_decrypt((const unsigned char *) (in + (i * 16)), out + i * 16, &sms4DecKey);
    }
    //去补位
    int padinglen = out[length - 1];
    memset(out + length - padinglen, 0, padinglen);

    jbyteArray array = env->NewByteArray(length - padinglen);
    env->SetByteArrayRegion(array, 0, length - padinglen, (const jbyte *) out);

    free(out);
    env->ReleaseByteArrayElements(in_, in, 0);
    env->ReleaseByteArrayElements(key_, key, 0);

    return array;
    }

    extern "C"
    JNIEXPORT jbyteArray JNICALL
    Java_com_yooking_gmssldemo_MainActivity_sm2Enc(JNIEnv *env,
    jobject instance,
    jbyteArray in_,
    jint length) {
    jbyte *in = env->GetByteArrayElements(in_, NULL);

    int iRet = 0;
    EC_KEY *ec_key = getEcKey();
    size_t sm2EncLen = SM2_MAX_PLAINTEXT_LENGTH;

    unsigned char *sm2EncMsg = (unsigned char *) malloc(SM2_MAX_PLAINTEXT_LENGTH);
    memset(sm2EncMsg, 0, SM2_MAX_PLAINTEXT_LENGTH);

    iRet = SM2_encrypt(NID_sm3,
    (const unsigned char *) in,
    (size_t) length,
    sm2EncMsg,
    &sm2EncLen,
    ec_key);

    if (!iRet) {
    ERR_load_ERR_strings();
    ERR_load_crypto_strings();

    unsigned long ulErr = ERR_get_error(); // 获取错误号

    const char *pTmp = ERR_reason_error_string(ulErr);
    puts(pTmp);
    }

    jbyteArray array = env->NewByteArray(sm2EncLen);
    env->SetByteArrayRegion(array, 0, sm2EncLen, (const jbyte *) sm2EncMsg);

    free(sm2EncMsg);
    EC_KEY_free(ec_key);
    env->ReleaseByteArrayElements(in_, in, 0);

    return array;
    }

    extern "C"
    JNIEXPORT jbyteArray JNICALL
    Java_com_yooking_gmssldemo_MainActivity_sm2Dec(JNIEnv *env,
    jobject instance,
    jbyteArray in_,
    jint length) {
    jbyte *in = env->GetByteArrayElements(in_, NULL);

    int iRet = 0;
    EC_KEY *ec_key = getEcKey();
    size_t sm2DecLen = 0;

    iRet = SM2_decrypt(NID_sm3,
    (const unsigned char *) in,
    (size_t) length,
    NULL,
    &sm2DecLen,
    ec_key);

    unsigned char *sm2DecMsg = (unsigned char *) malloc(sm2DecLen + 1);
    memset(sm2DecMsg, 0, sm2DecLen);

    iRet = SM2_decrypt(NID_sm3,
    (const unsigned char *) in,
    (size_t) length,
    sm2DecMsg,
    &sm2DecLen,
    ec_key);

    jbyteArray array = env->NewByteArray(sm2DecLen);
    env->SetByteArrayRegion(array, 0, sm2DecLen, (const jbyte *) sm2DecMsg);

    free(sm2DecMsg);
    EC_KEY_free(ec_key);
    env->ReleaseByteArrayElements(in_, in, 0);

    return array;
    }


    extern "C"
    JNIEXPORT jbyteArray JNICALL
    Java_com_yooking_gmssldemo_MainActivity_sm2Sign(JNIEnv *env,
    jobject instance,
    jbyteArray in_,
    jint length) {
    jbyte *in = env->GetByteArrayElements(in_, NULL);
    int iret = -1;

    EC_KEY *ec_key = getEcKey();


    size_t zlen = 0;
    iret = SM2_compute_message_digest(EVP_sm3(),
    EVP_sm3(),
    (const unsigned char *) in,
    length,
    SM2_DEFAULT_ID_GMT09,
    SM2_DEFAULT_ID_LENGTH,
    NULL,
    &zlen,
    ec_key);
    if (!iret) {
    return NULL;
    }
    unsigned char *z = (unsigned char *) malloc(zlen + 1);
    memset(z, 0, zlen + 1);
    iret = SM2_compute_message_digest(EVP_sm3(),
    EVP_sm3(),
    (const unsigned char *) in,
    length,
    SM2_DEFAULT_ID_GMT09,
    SM2_DEFAULT_ID_LENGTH,
    z,
    &zlen,
    ec_key);
    if (!iret) {
    return NULL;
    }

    unsigned int signLen = 0;
    iret = SM2_sign(NID_sm3, z, zlen, NULL, &signLen, ec_key);
    if (!iret) {
    return NULL;
    }
    unsigned char *signMsg = (unsigned char *) malloc(signLen + 1);
    memset(signMsg, 0, signLen + 1);
    iret = SM2_sign(NID_sm3, z, zlen, signMsg, &signLen, ec_key);
    if (!iret) {
    return NULL;
    }

    jbyteArray array = env->NewByteArray(signLen);
    env->SetByteArrayRegion(array, 0, signLen, (const jbyte *) signMsg);

    free(signMsg);
    free(z);
    EC_KEY_free(ec_key);
    env->ReleaseByteArrayElements(in_, in, 0);
    return array;
    }

    extern "C"
    JNIEXPORT jint JNICALL
    Java_com_yooking_gmssldemo_MainActivity_sm2Verify(JNIEnv *env,
    jobject instance,
    jbyteArray in_,
    jint length,
    jbyteArray sign_,
    jint signLen) {
    jbyte *in = env->GetByteArrayElements(in_, NULL);
    jbyte *sign = env->GetByteArrayElements(sign_, NULL);
    int iret = -1;
    EC_KEY *ec_key = getEcKey();

    size_t zlen = 0;
    iret = SM2_compute_message_digest(EVP_sm3(),
    EVP_sm3(),
    (const unsigned char *) in,
    length,
    SM2_DEFAULT_ID_GMT09,
    SM2_DEFAULT_ID_LENGTH,
    NULL,
    &zlen,
    ec_key);

    unsigned char *z = (unsigned char *) malloc(zlen + 1);
    memset(z, 0, zlen + 1);
    iret = SM2_compute_message_digest(EVP_sm3(),
    EVP_sm3(),
    (const unsigned char *) in,
    length,
    SM2_DEFAULT_ID_GMT09,
    SM2_DEFAULT_ID_LENGTH,
    z,
    &zlen,
    ec_key);
    if (!iret) {
    return -2;
    }

    iret = SM2_verify(NID_sm3, z, zlen, (const unsigned char *) sign, signLen, ec_key);

    free(z);
    EC_KEY_free(ec_key);
    env->ReleaseByteArrayElements(in_, in, 0);
    env->ReleaseByteArrayElements(sign_, sign, 0);
    return iret;
    }

    extern "C" JNIEXPORT jbyteArray JNICALL
    Java_com_yooking_gmssldemo_MainActivity_rsaEnc(JNIEnv *env, jobject instance, jbyteArray keys_, jbyteArray src_) {
    // LOGI("RSA->非对称密码算法,也就是说该算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密");
    jbyte *keys = env->GetByteArrayElements(keys_, NULL);
    jbyte *src = env->GetByteArrayElements(src_, NULL);
    jsize src_Len = env->GetArrayLength(src_);

    int ret = 0, src_flen = 0, cipherText_offset = 0, desText_len = 0, src_offset = 0;

    RSA *rsa = NULL;
    BIO *keybio = NULL;

    // LOGI("RSA->从字符串读取RSA公钥");
    keybio = BIO_new_mem_buf(keys, -1);
    // LOGI("RSA->从bio结构中得到RSA结构");
    rsa = PEM_read_bio_RSA_PUBKEY(keybio, NULL, NULL, NULL);
    // LOGI("RSA->释放BIO");
    BIO_free_all(keybio);

    int flen = RSA_size(rsa);
    desText_len = flen * (src_Len / (flen - 11) + 1);

    unsigned char *srcOrigin = (unsigned char *) malloc(src_Len);
    unsigned char *cipherText = (unsigned char *) malloc(flen);
    unsigned char *desText = (unsigned char *) malloc(desText_len);
    memset(desText, 0, desText_len);

    memset(srcOrigin, 0, src_Len);
    memcpy(srcOrigin, src, src_Len);

    // LOGI("RSA->进行公钥加密操作");
    //RSA_PKCS1_PADDING最大加密长度:128-11;RSA_NO_PADDING最大加密长度:128
    for (int i = 0; i <= src_Len / (flen - 11); i++) {
    src_flen = (i == src_Len / (flen - 11)) ? src_Len % (flen - 11) : flen - 11;
    if (src_flen == 0) {
    break;
    }

    memset(cipherText, 0, flen);
    ret = RSA_public_encrypt(src_flen, srcOrigin + src_offset, cipherText, rsa, RSA_PKCS1_PADDING);

    memcpy(desText + cipherText_offset, cipherText, ret);
    cipherText_offset += ret;
    src_offset += src_flen;
    }

    RSA_free(rsa);
    // LOGI("RSA->CRYPTO_cleanup_all_ex_data");
    CRYPTO_cleanup_all_ex_data();

    // LOGI("RSA->从jni释放数据指针");
    env->ReleaseByteArrayElements(keys_, keys, 0);
    env->ReleaseByteArrayElements(src_, src, 0);

    jbyteArray cipher = env->NewByteArray(cipherText_offset);
    // LOGI("RSA->在堆中分配ByteArray数组对象成功,将拷贝数据到数组中");
    env->SetByteArrayRegion(cipher, 0, cipherText_offset, (jbyte *) desText);
    // LOGI("RSA->释放内存");
    free(srcOrigin);
    free(cipherText);
    free(desText);

    return cipher;
    }

    extern "C" JNIEXPORT jbyteArray JNICALL
    Java_com_yooking_gmssldemo_MainActivity_rsaDes(JNIEnv *env, jobject instance, jbyteArray keys_, jbyteArray src_) {
    // LOGI("RSA->非对称密码算法,也就是说该算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密");
    jbyte *keys = env->GetByteArrayElements(keys_, NULL);
    jbyte *src = env->GetByteArrayElements(src_, NULL);
    jsize src_Len = env->GetArrayLength(src_);

    int ret = 0, src_flen = 0, plaintext_offset = 0, descText_len = 0, src_offset = 0;

    RSA *rsa = NULL;
    BIO *keybio = NULL;

    // LOGI("RSA->从字符串读取RSA私钥");
    keybio = BIO_new_mem_buf(keys, -1);
    // LOGI("RSA->从bio结构中得到RSA结构");
    rsa = PEM_read_bio_RSAPrivateKey(keybio, NULL, NULL, NULL);
    // LOGI("RSA->释放BIO");
    BIO_free_all(keybio);

    int flen = RSA_size(rsa);
    descText_len = (flen - 11) * (src_Len / flen + 1);

    unsigned char *srcOrigin = (unsigned char *) malloc(src_Len);
    unsigned char *plaintext = (unsigned char *) malloc(flen - 11);
    unsigned char *desText = (unsigned char *) malloc(descText_len);
    memset(desText, 0, descText_len);

    memset(srcOrigin, 0, src_Len);
    memcpy(srcOrigin, src, src_Len);

    // LOGI("RSA->进行私钥解密操作");
    //一次性解密数据最大字节数RSA_size
    for (int i = 0; i <= src_Len / flen; i++) {
    src_flen = (i == src_Len / flen) ? src_Len % flen : flen;
    if (src_flen == 0) {
    break;
    }

    memset(plaintext, 0, flen - 11);
    ret = RSA_private_decrypt(src_flen, srcOrigin + src_offset, plaintext, rsa, RSA_PKCS1_PADDING);

    memcpy(desText + plaintext_offset, plaintext, ret);
    plaintext_offset += ret;
    src_offset += src_flen;
    }

    RSA_free(rsa);
    // LOGI("RSA->CRYPTO_cleanup_all_ex_data");
    CRYPTO_cleanup_all_ex_data();

    // LOGI("RSA->从jni释放数据指针");
    env->ReleaseByteArrayElements(keys_, keys, 0);
    env->ReleaseByteArrayElements(src_, src, 0);

    jbyteArray cipher = env->NewByteArray(plaintext_offset);
    // LOGI("RSA->在堆中分配ByteArray数组对象成功,将拷贝数据到数组中");
    env->SetByteArrayRegion(cipher, 0, plaintext_offset, (jbyte *) desText);
    // LOGI("RSA->释放内存");
    free(srcOrigin);
    free(plaintext);
    free(desText);

    return cipher;
    }

    extern "C" JNIEXPORT jbyteArray JNICALL
    Java_com_yooking_gmssldemo_MainActivity_rsaSign(JNIEnv *env, jobject instance, jbyteArray keys_, jbyteArray src_) {
    // LOGI("RSA->非对称密码算法,也就是说该算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密");
    jbyte *keys = env->GetByteArrayElements(keys_, NULL);
    jbyte *src = env->GetByteArrayElements(src_, NULL);
    jsize src_Len = env->GetArrayLength(src_);

    unsigned int siglen = 0;
    unsigned char digest[SHA_DIGEST_LENGTH];

    RSA *rsa = NULL;
    BIO *keybio = NULL;

    // LOGI("RSA->从字符串读取RSA公钥");
    keybio = BIO_new_mem_buf(keys, -1);
    // LOGI("RSA->从bio结构中得到RSA结构");
    rsa = PEM_read_bio_RSAPrivateKey(keybio, NULL, NULL, NULL);
    // LOGI("RSA->释放BIO");
    BIO_free_all(keybio);

    unsigned char *sign = (unsigned char *) malloc(129);
    memset(sign, 0, 129);

    SHA1((const unsigned char *) src, src_Len, digest);
    RSA_sign(NID_sha1, digest, SHA_DIGEST_LENGTH, sign, &siglen, rsa);

    RSA_free(rsa);
    // LOGI("RSA->CRYPTO_cleanup_all_ex_data");
    CRYPTO_cleanup_all_ex_data();

    // LOGI("RSA->从jni释放数据指针");
    env->ReleaseByteArrayElements(keys_, keys, 0);
    env->ReleaseByteArrayElements(src_, src, 0);

    jbyteArray cipher = env->NewByteArray(siglen);
    // LOGI("RSA->在堆中分配ByteArray数组对象成功,将拷贝数据到数组中");
    env->SetByteArrayRegion(cipher, 0, siglen, (jbyte *) sign);
    // LOGI("RSA->释放内存");
    free(sign);

    return cipher;
    }


    extern "C" JNIEXPORT jint JNICALL
    Java_com_yooking_gmssldemo_MainActivity_rsaVerify(JNIEnv *env, jobject instance, jbyteArray keys_, jbyteArray src_, jbyteArray sign_) {
    // LOGI("RSA->非对称密码算法,也就是说该算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密");
    jbyte *keys = env->GetByteArrayElements(keys_, NULL);
    jbyte *src = env->GetByteArrayElements(src_, NULL);
    jbyte *sign = env->GetByteArrayElements(sign_, NULL);

    jsize src_Len = env->GetArrayLength(src_);
    jsize siglen = env->GetArrayLength(sign_);

    int ret;
    unsigned char digest[SHA_DIGEST_LENGTH];

    RSA *rsa = NULL;
    BIO *keybio = NULL;

    // LOGI("RSA->从字符串读取RSA公钥");
    keybio = BIO_new_mem_buf(keys, -1);
    // LOGI("RSA->从bio结构中得到RSA结构");
    rsa = PEM_read_bio_RSA_PUBKEY(keybio, NULL, NULL, NULL);
    // LOGI("RSA->释放BIO");
    BIO_free_all(keybio);

    SHA1((const unsigned char *) src, src_Len, digest);
    ret = RSA_verify(NID_sha1, digest, SHA_DIGEST_LENGTH, (const unsigned char *) sign, siglen, rsa);

    RSA_free(rsa);
    // LOGI("RSA->CRYPTO_cleanup_all_ex_data");
    CRYPTO_cleanup_all_ex_data();

    // LOGI("RSA->从jni释放数据指针");
    env->ReleaseByteArrayElements(keys_, keys, 0);
    env->ReleaseByteArrayElements(src_, src, 0);
    env->ReleaseByteArrayElements(sign_, sign, 0);

    return ret;
    }
------------本文结束感谢您的阅读------------

Thank you for your accept!