# 简版密码服务接入方案

# 1 文档说明

# 1.1 使用对象

接入密码服务产品的第三方应用相关人员

# 1.2 版本信息

版本信息 版本信息 修订人 修订内容
3.3 2023-03-26 SIMKEY团队 创建

# 2 术语及缩略语定义

下列术语、定义和缩略语适用于本标准

名词 解释
API Application Programming Interface,应用程序编程接口
LTE 3GPP Long Term Evolution,3GPP长期演进技术
VPN Virtual Private Network,虚拟专用网络
OA Office Automation,办公自动化
OTA Over The Air
SDK SoftwareDevelopment Kit,软件开发工具包
OMA Open Mobile API
UICC Universal Integrated Circuit Card
CRM Customer Relationship Management
  • 访问控制执行器(access control enforcer)

访问控制执行器,组成安全模块访问 API 的部分软件,它从安全模块上获取访问规则,并运用这些规则来控制设备应用,对于安全模块上各种应用程序的访问。

  • 终端设备(mobile device)

本规范中特指任何包含安全模块的终端设备,如移动电话。

  • 开放移动设备操作系统(open mobile OS)

允许加载第三方应用程序的移动设备操作系统

  • 安全模块(secure element)

可用于移动设备的智能卡芯片。例如 UICC 卡/SIM 卡、嵌入式安全模块、高 安全 SD 卡等

  • 安全模块应用(applet)

一个安装并运行在安全模块里面的应用。例如一个 Java 卡应用或一个 Native 卡应用。为与设备应用区别,本文档中统一称为“Applet”。

  • 终端应用(device a pplication)

一个安装并运行于移动设备上的应用程序,简称“应用”。本文中的手机终端 应用特指集成 CTPass SDK 包的手机应用程序。

  • 会话(session)

设备(例如手机终端)应用和安全模块之间打开的一个连接。

  • 通道(channel)

设备(例如手机终端)应用和 Applet 之间打开的一个连接。

# 3 Android Studio 工程配置

# 3.1 在项目中集成SDK

# 3.1.1 放置aar文件

将 libcissskf.aar 拷贝到工程 module 的 libs 目录下

# 3.1.2 放置so文件

将libLiteService.so文件按架构类型拷贝到工程 module 的jniLibs 目录下

# 3.1.2 添加配置

在 module 的 build.gradle 文件中添加aar和so文件配置

android分支内添加:
sourceSets {
    main {
       jniLibs.srcDirs = ['src/main/jniLibs']
    }
}

android分支外添加:
repositories {
    flatDir {
        dirs 'libs'
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])
    implementation 'org.bouncycastle:bcprov-jdk15on:1.65'
    implementation files('libs/libcissskf.aar')
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 3.1.3 添加依赖

在 module 的 build.gradle 中配置其他必须的依赖

implementation 'org.bouncycastle:bcprov-jdk15on:1.65'
1

# 3.1.4 添加外部库

Android9.0以后通过OMA访问SIM卡的库已经集成在Android系统中,为了兼容旧系统版本的手机,在 module 的 AndroidManifest.xml 配置 openmobileapi

在 application 节点里面面添加
<uses-library android:name="org.simalliance.openmobileapi"  android:required="false"/>
如下图:
1
2
3

# 3.1.5 添加权限

在module的AndroidManifest.xml中添加权限

<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.SMARTCARD" />
<uses-permission android:name="org.simalliance.openmobileapi.SMARTCARD" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
1
2
3
4
5
6
7
8
9

如果是 targetSdkVersion > = 23 时, 有的权限需要动态申请

# 3.2 应用混淆

在对应module的proguard-rules.pro文件中添加混淆,如下所示

## ----------------------------------
## ########## SIMKEY SKF ##########
## ----------------------------------
-keep class com.simkey.sec.libciss.card.skf.** {*;}
-keep class com.simkey.sec.libciss.card.apdu.OMAAPDUSenderForSKF {*;}
-keep class com.simkey.sec.liteservice.** {*;}
## ----------------------------------
## ########## oma ##########
## ----------------------------------
-keep class org.simalliance.openmobileapi.** { *; }
-dontwarn org.simalliance.openmobileapi.**
1
2
3
4
5
6
7
8
9
10
11

保证skf的sdk不被混淆, 否则无法和 SIM 卡进行交互

# 3.3 调用SDK

# 3.3.1 在 Application 里面的初始化

1.在 onCreate 方法中添加 CISSSKFInit.init 初始化方法进行初始化, 如果不进行此步骤则无法发送指令到SIM卡 参数:

表头 表头 表头 表头
context Context 上下文
scanBleNow boolean 单元格 是否立即扫描蓝牙设备, 如果使用”pcsc:Auto”来连接卡, 那么建议开启扫描. 注意: android api 23 及以上需要 app 进行动态权限申请

2.因简版密码服务中无连接SIM卡的接口,请使用如下方式连接:

参数 说明 备注
"pcsc:OMA" 仅使用 OMA 模式连接,CISSSKFInit.init初始化方法可以传入false
"pcsc:Auto" 自动模式, 优先使用 OMA, OMA 不通则扫描周围的蓝牙设备。如果扫描不到设备则连接失败。为了能够迅速的扫描到蓝牙设备,CISSSKFInit.init 初始化方法应该传入 true
"pcsc:Ble:xx" 仅蓝牙模式,需要传入蓝牙的 mac 地址,MAC 地址要大写。比如:"pcsc:Ble:00:B7:1D:0A:A5:01" CISSSKFInit.init初始化方法可以传入false

调用如下:

public class MyApp extends Application {
      private static Context context;
      @Override
      public void onCreate() {
          super.onCreate();
          boolean scanBleNow = false;//是否进行蓝牙扫描,false表示不进行蓝牙扫描
          CISSSKFInit.init(this, scanBleNow);
         //初始化之后可以设置日志显示与否, 默认不显示
         OMAAPDUSenderForSKF.getInstance().setLogAble(true);
          //连接卡,使用OMA通道,简版密码服务未提供连接卡的方式,此处代替连接卡
         OMAAPDUSenderForSKF.getInstance().connect("pcsc:OMA");
         //连接卡,使用自动,CISSSKFInit参数必须为true
         //OMAAPDUSenderForSKF.getInstance().connect("pcsc:Auto");
         //连接卡,使用蓝牙通道,不需要再扫描,CISSSKFInit参数可以为false
       //OMAAPDUSenderForSKF.getInstance().connect("pcsc:Ble:00:B7:1D:0A:A5:01");
      }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

将继承Application的类MyApp添加到AndroidManifest.xml中,如下图所示:

# 3.3.2 密码服务的初始化

先获取密码服务实例 LiteService (附录1)

LiteService liteService = new LiteService();
1

进行密码服务初始化

liteService.init();//调用所有接口之前先调用
1

如果不进行此操作,APP会闪退

# 3.3.3 在 Android中的使用

完成上述各个步骤之后,可以对密码服务接口进行调用了, 例子如下

String appName = "xxxxxx";
int result = liteService.openApplication(appName);
1
2

# 3.3.5 日志

默认不打印日志, 如果需要日志的话,则添加代码:

OMAAPDUSenderForSKF.getInstance().setLogAble(true);
1

日志会在 logcat 打印, 且会在手机的外部存储中保存到文件

public class MyApp extends Application {
     private static Context context;
     @Override
     public void onCreate() {
         super.onCreate();
         boolean scanBleNow = true;
         CISSSKFInit.init(this, scanBleNow);
         //初始化之后可以设置日志显示与否, 默认不显示
         OMAAPDUSenderForSKF.getInstance().setLogAble(true);
     }
}
1
2
3
4
5
6
7
8
9
10
11

# 附录

# 附录1

名称 说明 作用
LiteService 简版密码服务实例 用来进行接口调用
LiteConst 简版密码服务常量 用来提供常量参数
Envelop 封装后的数字信封 普通PO类
KeyInfo 非对称密钥的信息 普通PO类
MyLong 含有一个long型成员变量value 用来运送输入输出的数字

# 附录2

常量定义:

常量 含义
用户权限
ADMIN_TYPE 0 管理员PIN类型
USER_TYPE 1 用户PIN类型
读写权限
ACCESS_ANYONE 0 任何人
ACCESS_USER 1 用户权限
ACCESS_ADMIN 2 管理员权限
ACCESS_NEVER 4 不允许
分组密码算法
SGD_3DES 0x00000001 3DES算法
SGD_AES 0x00000010 AES算法
SGD_SM1 0x00000100 SM1算法
SGD_SM4 0x00000400 SM4算法
加解密模式
SGD_ECB 0x00000001
SGD_CBC 0x00000002
非对称密码算法标识
SGD_RSA 0x00010000 RSA算法
SGD_SM2 0x00020100 SM2椭圆曲线密码算法
密码杂凑算法标识
SGD_SM3 0x00000001 SM3杂凑算法
SGD_SHA1 0x00000002 SHA_1杂凑算法
SGD_SHA256 0x00000004 SHA_256杂凑算法
SGD_MD5 0x00000008 MD5杂凑算法

# 附录3

错误码:

名称 含义
SAR_OK 0x00000000 成功
SAR_FAIL 0x0A000001 失败
SAR_UNKNOWNER 0x0A000002 异常错误
SAR_NOSUPPORTYETERR 0x0A000003 不支持的服务
SAR_FILEERR 0x0A000004 文件操作错误
SAR_INVALIDHANDLEERR 0x0A000005 无效的句柄
SAR_INVALIDPARAMERR 0x0A000006 无效的参数
SAR_READFILEERR 0x0A000007 读文件错误
SAR_WRITEFILEERR 0x0A000008 写文件错误
SAR_NAMELENERR 0x0A000009 名称长度错误
SAR_KEYUSAGEERR 0x0A00000A 密钥用途错误
SAR_MODULUSLENERR 0x0A00000B 模的长度错误
SAR_NOTINITIALIZEERR 0x0A00000C 未初始化
SAR_OBJERR 0x0A00000D 对象错误
SAR_MEMORYERR 0x0A00000E 内存错误
SAR_TIMEOUTERR 0x0A00000F 超时
SAR_INDATALENERR 0x0A000010 输入数据长度错误
SAR_INDATAERR 0x0A000011 输入数据错误
SAR_GENRANDERR 0x0A000012 生成随机数错误
SAR_HASHOBJERR 0x0A000013 HASH对象错误
SAR_HASHERR 0x0A000014 HASH运算错误
SAR_GENRSAKEYERR 0x0A000015 产生RSA密钥错误
SAR_RSAMODULUSLENERR 0x0A000016 RSA密钥模长错误
SAR_CSPIMPRTPUBKEYERR 0x0A000017 CSP服务导入公钥错误
SAR_RSAENCERR 0x0A000018 RSA加密错误
SAR_RSADECERR 0x0A000019 RSA解密错误
SAR_HASHNOTEQUALERR 0x0A00001A HASH值不相等
SAR_KEYNOTFOUNTERR 0x0A00001B 密钥未发现
SAR_CERTNOTFOUNTERR 0x0A00001C 证书未发现
SAR_NOTEXPORTERR 0x0A00001D 对象未导出
SAR_DECRYPTPADERR 0x0A00001E 解密时做补丁错误
SAR_MACLENERR 0x0A00001F MAC长度错误
SAR_BUFFER_TOO_SMALL 0x0A000020 缓冲区不足
SAR_KEYINFOTYPRERR 0x0A000021 密钥类型错误
SAR_NOT_EVENTERR 0x0A000022 无事件错误
SAR_DEVICE_REMOVED 0x0A000023 设备已移除
SAR_PIN_INCORRECT 0x0A000024 PIN不正确
SAR_PIN_LOCKED 0x0A000025 PIN被锁死
SAR_PIN_INVALID 0x0A000026 PIN无效
SAR_PIN_LEN_RANGE 0x0A000027 PIN长度错误
SAR_USER_ALREADY_LOGGED_IN 0x0A000028 用户已经登录
SAR_USER_PIN_NOT_INITIALIZED 0x0A000029 没有初始化用户口令
SAR_USER_TYPE_INVALID 0x0A00002A PIN类型错误
SAR_APPLICATION_NAME_INVALID 0x0A00002B 应用名称无效
SAR_APPLICATION_EXISTS 0x0A00002C 应用已经存在
SAR_USER_NOT_LOGGED_IN 0x0A00002D 用户没有登录
SAR_APPLICATION_NOT_EXISTS 0x0A00002E 应用不存在
SAR_FILE_ALREADY_EXIST 0x0A00002F 文件已经存在
SAR_NO_ROOM 0x0A000030 空间不足
SAR_FILE_NOT_EXIST 0x0A000031 文件不存在
SAR_REACH_MAX_CONTAINER_COUNT 0x0A000032 已达到最大可管理容器数