安卓APP开发中,如何使用加密芯片?

news2024/12/27 12:48:24

加密芯片是一种专门设计用于保护信息安全的硬件设备,它通过内置的加密算法对数据进行加密和解密,以防止敏感数据被窃取或篡改。如下图HD-RK3568-IOT工控板,搭载ATSHA204A加密芯片,常用于有安全防护要求的工商业场景,下文将为大家介绍安卓APP开发中,如何使用此类加密芯片。

3568开发板

1. Android Studio工具配置

JNI(Java Native Interface,Java 本地接口)是 Java 生态的特性,它扩展了 Java 虚拟机的能力,使得 Java 代码可以与 C/C++ 代码进行交互。通过 JNI 接口,Java 代码可以调用 C/C++ 代码,C/C++ 代码也可以调用 Java 代码。虽然 Java 是平台无关性语言,但运行 Java 语言的虚拟机是运行在具体平台上的,所以 Java 虚拟机是平台相关的。因此,对于调用平台 API 的功能时,虽然在 Java 语言层是平台无关的,但背后只能通过 JNI 技术在 Native 层分别调用不同平台 API。类似的,对于有操作硬件需求的程序,也只能通过 C/C++ 实现对硬件的操作,再通过 JNI 调用。为了支持JNI的开发,在Android Studio工具中需要NDK(Native Development Kit)的支持。

1.png

图 1.1:添加NDK和CMake支持

点击Androis Studio 的 File->settings菜单,打上上面的settings页面,首先找到Android SDK的设定位置,Android Studio版本不一样时,其Android SDK所处的子项可能略有差异,然后点击SDK Tools页签,勾选上NDK和CMake的支持,然后安装它们。

2. 新建Native C++工程

点击 File->New project,然后选中“Native C++” 工程模板,创建一个 C++工程。最后点击“Next” 按钮, 如下图所示:

2.png

图 2.1:新建Native C++项目

接着填写工程的名字,包名,工程保存的位置以及语言,然后点击“Next” 按钮,如下图所示:

3.png

图 2.2:native项目设置

接着进行C++标准设定,这里可以根据熟悉的语言标准进行选择,最后点击“Finish”完成设定。

4.png

图 2.3:C++ Standard选择

完成后,新建的项目窗口如下:

5.png

图 2.4:新建项目全貌

导航栏作用可以通过左侧项目工具视图体现,菜单栏也可以先隐藏而在需要时显示,为使窗口空间的有效利用,通过View->Appearance将菜单栏隐藏,并将导航信息设定为在下方的Status Bar中显示。

3. Native项目开发

3.1 CPP开发

在窗口的左侧边沿是一条“Tool Window Bar”,用于选择左侧窗口“Tool Window”的内容,在窗口的左上角有一个 

6.png

 图标,表示“Tool Window”显示为项目,点击该图标会有不同的视图选择,这里默认是“Android”视图,现在点击 “Android”标签,在下拉视图选项中选择“Project File” 视图:

7.png

图 3.1:项目视图选择

8.png

图 3.2:Project Files显示

cryptosdr/app/src/main/AndroidManifest.xml 是一个清单文件,在每个 android 应用项目必有的, 它负责向 Android构建工具,此文件是自动生成的。

cryptosdr/app/src/main/java/com/vanxoak/cryptosdr/MainActivity.java 是描述程序逻辑的 java 文件。

cryptosdr/app/src/main/cpp下面有两个文件,是我们要进行native c++开发的地方:

CMakeLists.txt:编译脚本, 用于告知如何编译项目中的本地库。

native-lib.cpp:创建的本地库示例代码模板, 后期代码编写主要在这个文件里面进行。现在分别详细介绍一下这两个文件,CMakeLists.txt 解释如下:

cmake_minimum_required(VERSION 3.22.1)   #设置 Cmake 的最低版本project("cryptosdr")    #设置 Cmake 构建的项目名称add_library(${CMAKE_PROJECT_NAME} SHARED   #设定项目为动态库,有SHARED指定# List C/C++ source files with relative paths to this CMakeLists.txt.        native-lib.cpp)      #设定该库包含的源码为native-lib.cpp,若后面添加其它源码,需要在此处追加target_link_libraries(${CMAKE_PROJECT_NAME}# List libraries link to the target library        androidlog)

navtive-lib.cpp 文件, 这个文件是本地库的 C++源码。我们需要在这里定义本地库对 java(Android) 层提供的接口。在 java 中调用我们定义和提供的接口, 就能实现 java 操纵 c++的能力,这里是自动生成的一个示例:

#include<jni.h>#include<string>extern"C"JNIEXPORT jstring JNICALLJava_com_vanxoak_cryptosdr_MainActivity_stringFromJNI(        JNIEnv* env,        jobject /* this */) {std::string hello = "Hello from C++";return env->NewStringUTF(hello.c_str());}

我们需要对navtive-lib.cpp实现的内容进行修改,上面给了一个范例,我们也可以通过其它的方式让这个文件更接近我们需要的。

3.2 建立接口类文件

现在新建一个Java所需要的接口类,在工具窗口的app/src/main/java/com/vanxoak/cryptosdr文件夹上右键弹出菜单上新建一个“Java Class”:

11.png

图 3.3:新建Java Class

在新建串口中输入类名称“Rjgt102”,并使用默认Class选项:

12.png

图 3.4:New Rjgt102 Class

新建完成后会生成一个Rjgt102.class的文件,在Edit Window中编辑类的接口信息,最终得到的文件如下:

package com.vanxoak.cryptosdr;publicclassRjgt102{publicnativeintInit();   //打开加密芯片publicnativevoidClose(); //关闭加密芯片publicnativeintAuthDev(); //校验加密芯片是否来自vanxoakpublicnativeintUpdatePage(byte page_id, byte[] page_buf); //更新加密芯片page数据publicnativeintReadPage(byte page_id, byte[] page_buf); //读取加密芯片page数据publicnativeintGetUsid(byte[] usid_buf); //读取加密芯片内的USIDpublicnativeintCalMac(byte[] random_buf, byte page_id, byte[] mac_buf); //给加密芯片输入}

3.3 通过类文件生成JNI接口

点击左侧Tool Window Bar的

图标,或直接使用“Alt+F12”来打开终端窗口:

15.png

图 3.5:Terminal窗口

运行下面的命令:

E:\RK3568_APP\cryptoSdr> cd app\src\mainE:\RK3568_APP\cryptoSdr\app\src\main> javac -encoding utf-8 -h cpp java\com\vanxoak\cryptosdr\Rjgt102.java

命令执后,在cpp目录下会生成一个com_vanxoak_cryptosdr_Rjgt102.h的头文件,通过右键点击Tool window中的cpp文件夹并”Reload from Disk”可以在Tool window中看到这一文件,打开文件可以看到下面的文件内容:

/* DO NOT EDIT THIS FILE - it is machine generated */#include<jni.h>/* Header for class com_vanxoak_cryptosdr_Rjgt102 */#ifndef _Included_com_vanxoak_cryptosdr_Rjgt102#define _Included_com_vanxoak_cryptosdr_Rjgt102#ifdef __cplusplusextern"C" {#endif/*   * Class:     com_vanxoak_cryptosdr_Rjgt102   * Method:    Init   * Signature: ()I   */JNIEXPORT jint JNICALL Java_com_vanxoak_cryptosdr_Rjgt102_Init(JNIEnv *, jobject);/*   * Class:     com_vanxoak_cryptosdr_Rjgt102   * Method:    Close   * Signature: ()V   */JNIEXPORT void JNICALL Java_com_vanxoak_cryptosdr_Rjgt102_Close(JNIEnv *, jobject);/*   * Class:     com_vanxoak_cryptosdr_Rjgt102   * Method:    AuthDev   * Signature: ()I   */JNIEXPORT jint JNICALL Java_com_vanxoak_cryptosdr_Rjgt102_AuthDev(JNIEnv *, jobject);/*   * Class:     com_vanxoak_cryptosdr_Rjgt102   * Method:    UpdatePage   * Signature: (B[B)I   */JNIEXPORT jint JNICALL Java_com_vanxoak_cryptosdr_Rjgt102_UpdatePage(JNIEnv *, jobject, jbyte, jbyteArray);/*   * Class:     com_vanxoak_cryptosdr_Rjgt102   * Method:    ReadPage   * Signature: (B[B)I   */JNIEXPORT jint JNICALL Java_com_vanxoak_cryptosdr_Rjgt102_ReadPage(JNIEnv *, jobject, jbyte, jbyteArray);/*   * Class:     com_vanxoak_cryptosdr_Rjgt102   * Method:    GetUsid   * Signature: ([B)I   */JNIEXPORT jint JNICALL Java_com_vanxoak_cryptosdr_Rjgt102_GetUsid(JNIEnv *, jobject, jbyteArray);/*   * Class:     com_vanxoak_cryptosdr_Rjgt102   * Method:    CalMac   * Signature: ([BB[B)I   */JNIEXPORT jint JNICALL Java_com_vanxoak_cryptosdr_Rjgt102_CalMac(JNIEnv *, jobject, jbyteArray, jbyte, jbyteArray);#ifdef __cplusplus }#endif#endif

其中的内容主要是我们将要实现的功能,我们在native-lib.cpp中实现上面的函数,并删除native-lib.cpp原先自动生成的Java_com_vanxoak_cryptosdr_MainActivity_stringFromJNI函数,并重新构建整个工程,有于Rjgt102属于加密芯片,源码中含有密钥信息,这里不暂时native-lib.cpp的源码内容,并且接下来我们将利用得到的动态库重新改造该项目使之仅使用生成的动态库而不再包含源码。

在构建完成后可以发现生成了多个libcryprosdr.so文件,以满足多个架构的需求:

20.png

图 3.6:多架构下libcryprosdr.so文件

3.4 MainActivity及布局文件的编写

我们要实现的界面效果, 如下图所示。activity_main.xml 里面定义了一个主体的LinearLayout,其中分布有2个TableLayout, 然后在TableRow中分布TextView,Button,EditText以及Spinner控件,具体的编写方法请参考本文档配套资料提供的应用程序源码。

21.png

图 3.7:cryptoSdr显示界面

MainActivity.java 中要写实现控件功能的逻辑代码。在此文件中, 将会对之前定义的Rjgt102接口进行调用。

3.4.1 Usid的显示

我们希望打开应用时就能显示该Rjgt102芯片的Usid,这就需要我们在MainActivity的onCreate函数中就利用JNI来访问Rjgt102芯片来获取Usid信息,下面是获取流程:

publicclassMainActivityextendsAppCompatActivity {private Rjgt102 mRjgt102 = new Rjgt102(); #定义一个私有对象,后续在方法中使用protectedvoidonCreate(Bundle savedInstanceState) {mRjgt102.Init();           #连接Rjgt102芯片byte[] usid=newbyte[8];mRjgt102.GetUsid(usid);      #利用native方法获取usidtv.setText(bytesToHex(usid));         #把byte数组转化为十六进制字符串并显示}}

3.4.2   选择所操作的page对象

读取page或者更新page内容都需要明确的page_id作为对象,page_id的选择是通过Spinner控件进行的,下面是page_id选择的代码示例:

publicclassMainActivityextendsAppCompatActivity {private Integer pageId = 1;   #定义一个pageId对象,并默认为page 1protectedvoidonCreate(Bundle savedInstanceState) {Spinner spinnerPageId = findViewById(R.id.spin_page_id);        spinnerPageId.setSelection(0);        spinnerPageId.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {            @OverridepublicvoidonItemSelected(AdapterView<?> parent, View view, int pos, long id) {// TODOif (pos == 1) {                    pageId = 2;                } elseif (pos == 2) {                    pageId = 3;                } else {                    pageId = 1;                }            }            @OverridepublicvoidonNothingSelected(AdapterView<?> adapterView) {            }        });}}

实际上是对Spinner对象的ItemSelected事件进行监听来获取的pageId。

3.4.3 读取page内容

读取page内容需要通过READPAGE按钮触发:

publicclassMainActivityextendsAppCompatActivity {protectedvoidonCreate(Bundle savedInstanceState) {Button btnReadPg = (Button) findViewById(R.id.readPageButton);        btnReadPg.setOnClickListener(new View.OnClickListener() {            @OverridepublicvoidonClick(View v) {byte[] pageData=newbyte[32];                mRjgt102.ReadPage(pageId.byteValue(),pageData);   #读取Page                TextView tv =   findViewById(R.id.pageDataEditText);                tv.setText(bytesToHex(pageData));              #16进制显示page内容            }        });}}

3.4.4   更新page内容

更新page内容需要通过READPAGE按钮触发:

publicclassMainActivityextendsAppCompatActivity {protectedvoidonCreate(Bundle savedInstanceState) {Button btnUpdatePg = (Button) findViewById(R.id.updatePageButton);        btnUpdatePg.setOnClickListener(new View.OnClickListener() {            @OverridepublicvoidonClick(View v) {byte[] pageData = newbyte[32];                TextView tv =   findViewById(R.id.pageDataEditText);                String PageStr = String.valueOf(tv.getText());       #读取用户输入if(PageStr.length() > 64 ){           #如果用户输入错误,给出提示                    builder = new AlertDialog.Builder(mContext);                    alert = builder.setTitle("系统提示:")                            .setMessage("page date最多能容纳32字节,\n所以这里最多只能输入不超过64个16进制字符")                            .setPositiveButton("确定", null).create();   //创建AlertDialog对象                    alert.show();                }else {byte[] pageStrData = hexStringToByteArray(PageStr);    #转为byte数组int i=0;for(;i<pageStrData.length;i++)                        pageData[i]=pageStrData[i];for(;i<32;i++)                        pageData[i]=0;                    mRjgt102.UpdatePage(pageId.byteValue(), pageData);   #更新page内容                }            }        });}}

4. 转为JniLibs项目

在上一章Native项目开发完成后,整个应用功能已可使用,但由于native c++代码中含有敏感信息,需要保护而不公开native部分代码,则需要将该部分代码转为应用包含JniLibs的方式。

4.1 新建jniLibs目录

需要在app\src\main上右键单击菜单中选择New->Directory:

26.png

图 4.1:new Direcrory

将新建的目录命名为jniLibs。

4.2 拷贝libcryprosdr.so到jniLibs

现在将libcryprosdr.so文件拷贝进来:

27.png

图 4.2:拷贝libcryprosdr.so文件到jniLibs

4.3 删除cpp目录

现在需要删除敏感native c++源码了,直接在src\app\src\main\cpp上右键单击菜单中选择Delete:

28.png

图 4.3:删除cpp目录

同样方式可对中间过程文件存储文件夹src\app\.cxx进行删除。

4.4 删除对cpp目录的编译引用

在删除了cpp目录后,还需要删除项目中对cpp的编译部分,这里需要修改app\build.gradle文件,使之不再进行externalNativeBuild:

29.png

图 4.4:删除对cpp的编译

将上面内容删除后重新编译工程即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2229044.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

什么是x86架构,什么是arm架构

什么是 x86 架构&#xff1f; x86 架构是一种经典的指令集架构&#xff08;ISA&#xff09;&#xff0c;最早由英特尔在 1978 年推出&#xff0c;主要用于 PC、服务器等领域。 它是一种复杂指令集计算&#xff08;CISC&#xff09;架构&#xff0c;支持大量的复杂指令和操作&…

知识分享 | SNP检测试剂盒开发注意事项及启衡星CDMO案例分享

一、SNP检测方法 常规有阵列的杂交、qPCR和测序等多种方法&#xff0c;其中基于qPCR方法的SNP检测试剂盒因具有快速、简便的优势&#xff0c;已有大量检测试剂盒上市。如&#xff1a;人CYP2C9和VKORC1基因检测试剂盒、人类SLCO1B1和ApoE基因分型检测试剂盒、人ADRB1&#xff0…

详解varint,zigzag编码, 以及在Go标准库中的实现

文章目录 为啥需要varint编码为啥需要zigzag编码varint编码解码 zigzag编码解码 局限性 为啥需要varint编码 当我们用定长数字类型int32来表示整数时&#xff0c;为了传输一个整数1&#xff0c;我们需要传输00000000 00000000 00000000 00000001 32 个 bits&#xff0c;而有价…

又一部神作登场,MTC高分8.8认证,堪称年度佳片

威尼斯电影节上&#xff0c;布拉迪科贝特导演的新作《粗野派》大放异彩。这部电影&#xff0c;不仅在现场收获了观众的真诚掌声&#xff0c;甚至被不少专业影评人评为“2024年度最佳电影”&#xff0c;而这个评价背后&#xff0c;是一部作品真正打动人心的力量。 布拉迪科贝特&…

低代码平台如何通过AI赋能,实现更智能的业务自动化?

引言 随着数字化转型的加速推进&#xff0c;企业在日常运营中面临的业务复杂性与日俱增。如何快速响应市场需求&#xff0c;优化流程&#xff0c;并降低开发成本&#xff0c;成为各行业共同关注的核心问题。低代码平台作为一种能够快速构建应用程序的工具&#xff0c;因其可视化…

进程、孤儿进程、僵尸进程、fork、wait简介

进程相关概念 程序和进程 程序&#xff1a;是指编译好的二进制文件&#xff0c;在磁盘上&#xff0c;占用磁盘空间, 是一个静态的概念. 进程&#xff1a;一个启动的程序&#xff0c; 进程占用的是系统资源&#xff0c;如&#xff1a;物理内存&#xff0c;CPU&#xff0c;终端等…

已解决:VS2022一直显示编译中但无法运行的情况

本问题已得到解决&#xff0c;请看以下小结&#xff1a; 关于《VS2022一直显示编译中但无法运行的情况》的解决方案 记录备注报错时间2024年报错版本VS2022报错复现突然VS2022不能启动&#xff0c;一直显示编译中&#xff0c;取消重试无效&#xff0c;重新生成解决方案无效报错…

12. MapReduce全局计数器

一. 计数器概述 在执行MapReduce程序时&#xff0c;控制台的输出中一般会包含如下内容。 这些输出就是MapReduce的全局计数器的输出信息。计数器是用来记录job的执行进度和状态的&#xff0c;它的作用可以理解为日志&#xff0c;方便用户了解任务的执行状况&#xff0c;辅助…

Springboot集成阿里云通义千问(灵积模型)

我这里集成后&#xff0c;做成了一个工具jar包&#xff0c;如果有不同方式的&#xff0c;欢迎大家讨论&#xff0c;共同进步。 集成限制&#xff1a; 1、灵积模型有QPM(QPS)限制&#xff0c;每个模型不一样&#xff0c;需要根据每个模型适配 集成开发思路&#xff1a; 因有…

今年双11,拼多多吹“新”风

文 | 螳螂观察 作者 | 陈小江 这届双11真变了。 以前提到双11&#xff0c;不管平台、商家全都盯着价格。但今年不一样。这届双11给出了新解法——平台不再把“我的价格比你低”挂在嘴边&#xff0c;转而更关心消费者体验和为商家减负。 双11这艘大船&#xff0c;在航行到第…

005 IP地址的分类

拓扑结构如下 两台主机处于同一个网关下&#xff0c;通过ping命令检测&#xff0c;可以连通 &nbps; 拓扑结构如下 使用ping 检查两台电脑是否相通, 因为网络号不一样&#xff0c;表示两台电脑不在同一个网络&#xff0c;因此无法连通 拓扑结构如下 不在同一网络的PC要相…

记本地第一次运行seatunnel示例项目

前置 静态源码编译通过&#xff1a;https://blog.csdn.net/u011924665/article/details/143372464 参考 seatunnel官方的开发环境搭建文档&#xff1a;https://seatunnel.incubator.apache.org/zh-CN/docs/2.3.5/contribution/setup 安装scala 下载scala 去官网下载&…

《暗河传》 顺利杀青,苏棋演绎“千面鬼”慕婴引期待

近日&#xff0c;由龚俊、彭小苒、常华森、杨雨潼等一众优秀演员出演的古装武侠剧《暗河传》顺利杀青&#xff0c;00后小花苏棋饰演的“千面鬼”慕婴一角也收获了许多关注的目光。 《暗河传》凭借其精彩的剧情和庞大的粉丝基础&#xff0c;自开拍起便备受关注。在剧中&#xff…

推荐一个没有广告,可以白嫖的产品宣传册转换翻页电子书的网站

​随着数字化时代的到来&#xff0c;传统的纸质宣传册逐渐被电子书所取代。为了满足企业和个人对高效、便捷的电子宣传册制作需求&#xff0c;许多在线平台应运而生。今天&#xff0c;就让我为您推荐一个无需广告干扰、完全免费使用的在线宣传册转换翻页电子书网站——【FLBOOK…

QT 从ttf文件中读取图标

最近在做项目时&#xff0c;遇到需要显示一些特殊字符的需求&#xff0c;这些特殊字符无法从键盘敲出来&#xff0c;于是乎&#xff0c;发现可以从字体库文件ttf中读取显示。 参考博客&#xff1a;QT 图标字体类IconHelper封装支持Font Awesome 5-CSDN博客 该博客封装的很不错…

[Linux关键词]unmask,mv,dev/pts,stdin stdout stderr,echo

希望你开心&#xff0c;希望你健康&#xff0c;希望你幸福&#xff0c;希望你点赞&#xff01; 最后的最后&#xff0c;关注喵&#xff0c;关注喵&#xff0c;关注喵&#xff0c;大大会看到更多有趣的博客哦&#xff01;&#xff01;&#xff01; 喵喵喵&#xff0c;你对我真的…

人工智能与伦理:我们应该如何平衡科技与人性?

内容概要 在这个瞬息万变的时代&#xff0c;人工智能的迅猛发展让我们面对前所未有的伦理困境。科技进步带来了便利&#xff0c;但同时也亟需我们反思如何对待人性。尤其是在实现算法透明性时&#xff0c;我们要确保每一个决策背后都能被理解与追溯&#xff0c;这不仅是对技术…

聚水潭数据集成到MySQL的技术实操与解决方案

聚水潭数据集成到MySQL的技术案例分享 在现代企业的数据管理过程中&#xff0c;如何高效、可靠地实现不同系统之间的数据对接是一个关键问题。本案例将聚焦于“聚水谭-仓库查询单-->BI邦盈-仓库表”的数据集成方案&#xff0c;详细探讨如何通过轻易云数据集成平台&#xff…

Mybatis-03.入门-配置SQL提示

一.配置SQL提示 目前的Springboot框架在mybatis程序中编写sql语句并没有给到任何的提示信息&#xff0c;这对于开发者而言是很不友好的。因此我们需要配置SQL提示。 配置SQL提示 这样再去写SQL语句就会有提示了。 但是会发现指定表名时并没有给出提示。这是因为&#xff1a…

计算机视觉中的点算子:从零开始构建

Hey小伙伴们&#xff01;今天我们要聊的是一个非常基础但极其重要的计算机视觉技术——点算子&#xff08;Point Operators&#xff09;。点算子主要用于对图像的每个像素进行独立的处理&#xff0c;比如亮度调整、对比度增强、灰度化等。通过这些简单的操作&#xff0c;我们可…