首页 > 其他分享 >安卓APP开发中,如何使用加密芯片?

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

时间:2024-11-01 14:20:45浏览次数:4  
标签:Rjgt102 加密 vanxoak 安卓 cryptosdr page Java com APP

加密芯片是一种专门设计用于保护信息安全的硬件设备,它通过内置的加密算法对数据进行加密和解密,以防止敏感数据被窃取或篡改。如下图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\main
E:\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 __cplusplus
extern "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信息,下面是获取流程:

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

3.4.2   选择所操作的page对象

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

public class MainActivity extends AppCompatActivity {
…
private Integer pageId = 1;  #定义一个pageId对象,并默认为page 1
…
protected void onCreate(Bundle savedInstanceState) {
…
Spinner spinnerPageId = findViewById(R.id.spin_page_id);
        spinnerPageId.setSelection(0);
        spinnerPageId.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
                // TODO
                if (pos == 1) {
                    pageId = 2;
                } else if (pos == 2) {
                    pageId = 3;
                } else {
                    pageId = 1;
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {

            }
        }); 
…
}
…
}

 

 

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

3.4.3 读取page内容

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

public class MainActivity extends AppCompatActivity {
…
protected void onCreate(Bundle savedInstanceState) {
…
Button btnReadPg = (Button) findViewById(R.id.readPageButton);
        btnReadPg.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                byte[] pageData=new byte[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按钮触发:

public class MainActivity extends AppCompatActivity {
…
protected void onCreate(Bundle savedInstanceState) {
…
Button btnUpdatePg = (Button) findViewById(R.id.updatePageButton);
        btnUpdatePg.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                byte[] pageData = new byte[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的编译

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

标签:Rjgt102,加密,vanxoak,安卓,cryptosdr,page,Java,com,APP
From: https://www.cnblogs.com/vanxoak/p/18520085

相关文章

  • 安卓dispatchKeyEvent事件
    示例:publicclassMyActivityextendsActivity{@OverridepublicbooleandispatchKeyEvent(KeyEventevent){//检查是否按下了回退键(通常是物理按键或者是导航键)if(event.getKeyCode()==KeyEvent.KEYCODE_BACK){//检查事件类......
  • IDA修改WeChatAppEx,打补丁提示 Permission denied
    手贱,升级了下PC微信的版本,结果导致微信内置浏览器上的开发者模式(Devtools)失效,有时候需要在微信环境中看下别人的HTML不是很方便,特别是对于微信视频号中的视频更是看不到。新版本的已经没有【检查】这个选项了操作步骤如下:复制一份WeChatAppEx.exe,退出登录的PC微信,使用IDA......
  • 24小时搜书官网及zlibrary中文网址/客户端app
    24小时搜书(24hBookstore):一个免费电子书下载网站,支持通过书名、作者、出版社和ISBN编号等方式搜索和下载电子书。网站操作简单,直接下载无需多余步骤,支持azw3、mobi、epub、pdf等多种格式筛选。无论是通过书名、作者、出版社还是ISBN编号进行搜索。以下是一些使用这个网站的要点......
  • 用H5开发APP和用原生代码开发APP有什么区别
    使用H5开发APP和使用原生代码开发APP的区别主要体现在:1.开发过程不同;2.性能与效率不同;3.用户体验不同;4.兼容性问题不同;5.维护和更新方式不同。总的来说,H5开发更侧重于跨平台兼容和快速开发,而原生开发则注重应用性能和优异的用户体验。1.开发过程不同H5开发,即使用HTML5、CSS3......
  • Android APP如何获取设备网线插拔的状态
    我们的Android设备终端是支持有线接入的,现在有个需求是查询设备是否接入有线,查了下Android标准API没有找到查询有线接入与否的方法。后来与做系统的同事沟通,他告诉我可以通过cat/sys/class/net/eth0/operstate命令获取,UP表示接入,DOWN表示未接入。然后顺便扩展查询了下相关资......
  • 深入浅出:AutoMapper 的使用与最佳实践
    在现代软件开发中,特别是在.NET环境中,数据传输对象(DTO)与实体模型之间的映射是一个常见的需求。AutoMapper是一个强大的库,可以简化这一过程,减少样板代码,提高开发效率。本文将详细讲解AutoMapper的基本概念、各种用法以及最佳实践。什么是AutoMapper?AutoMapper是一个对象到......
  • App Cleaner & Uninstaller 中文激活版安装包 App Cleaner & Uninstaller 软件卸载清
    AppCleaner&Uninstaller是一款专为Mac用户设计的强大卸载工具。它能够深度卸载应用程序,不仅移除主程序,还彻底清理相关的配置文件、依赖文件等,确保卸载干净无残留。同时,该软件具备智能扫描功能,预览并列出所有安装的应用程序,方便用户选择卸载。此外,AppCleaner&Uninstaller还......
  • java计算机毕业设计员工工作助手app(开题+程序+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容一、研究背景随着信息技术的飞速发展,移动办公成为现代企业管理的重要趋势。在企业日常运营中,员工工作涉及到众多事务,如部门间的协作、员工个人工作的管理、各......
  • 基于安卓Android的自来水收费系统APP(源码+文档+部署+讲解)
    !!!!!!!!!选题不知道怎么选不清楚自己适合做哪块内容都可以免费来问我会持续一直更新下去有问必答一键收藏关注不迷路源码获取:https://pan.baidu.com/s/1aRpOv3f2sdtVYOogQjb8jg?pwd=jf1d提取码:jf1d !!!!!!!!!项目介绍随着智能水务管理的发展和用户对便捷服务的需求增加,一个功能全......
  • 基于SpringBoot+Vue+uniapp的宿舍管理系统的详细设计和实现(源码+lw+部署文档+讲解等)
    文章目录前言详细视频演示具体实现截图技术栈后端框架SpringBoot前端框架Vue持久层框架MyBaitsPlus系统测试系统测试目的系统功能测试系统测试结论为什么选择我代码参考数据库参考源码获取前言......