移动端 [Android iOS] 压缩 ECDSA PublicKey

移动端 [Android & iOS] 压缩 ECDSA PublicKey

  • Android
  • iOS

使用 Android KeyStore 和 iOS 的 Secure Enclave 提供的安全能力使用 P-256 来对 API 请求进行签名,服务器端再进行验证。

但是发现不论是 iOS 还是安卓都没有提供一个便捷的方式从 iOS 的SecKeyCopyExternalRepresentation(SecKeyCopyPublicKey) 和 Android 的 KeyPair 中得到 33-bytes 的 compressed public key。

压缩公钥(Compressed Public Key)是一种公钥编码方式,可以将 ECC(椭圆曲线密码学)公钥从 64 个字节压缩为 33 个字节。这种编码方式由一个字节的标识符和32个字节的公钥坐标的一部分(y坐标)组成,从而实现了公钥的压缩。在使用压缩公钥时,可以减少传输的数据量和存储空间,同时保持相同的安全性和加密效果。压缩公钥广泛应用于比特币、以太坊等区块链领域中。

compressed_public_key = y is even?0x02:0x03 + x

Android

private fun secp256r1JKeyPair(packageManager: PackageManager,alias: String,throwIfNotExists: Boolean = false,
): KeyPair {val ks: KeyStore = KeyStore.getInstance(storeProvider).apply { load(null) }val keyPair: KeyPair = if (ks.containsAlias(alias)) {val entry = ks.getEntry(alias, null)if (entry !is KeyStore.PrivateKeyEntry) {throw TypeCastException()}KeyPair(entry.certificate.publicKey, entry.privateKey)} else if (throwIfNotExists) {throw KeyStoreException("No key was found with the alias $alias.")} else {val kpg: KeyPairGenerator =KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, storeProvider)var properties =KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT or KeyProperties.PURPOSE_SIGN or KeyProperties.PURPOSE_VERIFYval parameterSpec = KeyGenParameterSpec.Builder(alias, properties).apply {setAlgorithmParameterSpec(ECGenParameterSpec("secp256r1"))setDigests(KeyProperties.DIGEST_SHA256)if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && hasStrongBox(packageManager)) {setIsStrongBoxBacked(true)}}.build()kpg.initialize(parameterSpec)kpg.generateKeyPair()}return keyPair
}@OptIn(ExperimentalUnsignedTypes::class)
fun bnUByteArrayToUByteArray(bnUByteArray: UByteArray, expectLength: Int): UByteArray {if (bnUByteArray.size == expectLength + 1) {return bnUByteArray.sliceArray(1..expectLength)}if (bnUByteArray.size < expectLength) {return UByteArray(expectLength - bnUByteArray.size) { UByte.MIN_VALUE } + bnUByteArray}return bnUByteArray
}@OptIn(ExperimentalUnsignedTypes::class)
fun secp256r1PublicKey(packageManager: PackageManager,alias: String
): UByteArray {val kp = secp256r1JKeyPair(packageManager, alias)val publicKey = kp.public as ECPublicKey;val point = publicKey.wval x: BigInteger = point.affineXval y: BigInteger = point.affineYval xBytes: UByteArray = bnUByteArrayToUByteArray(x.toByteArray().toUByteArray(), 32)val yFLag = UByteArray(1)yFLag[0] = (if (y.testBit(0)) 0x03 else 0x02).toUByte()return yFLag + xBytes
}@OptIn(ExperimentalUnsignedTypes::class)
fun secp256r1Sign(packageManager: PackageManager,alias: String,payload: ByteArray
): UByteArray {val privateKey =secp256r1JKeyPair(packageManager, alias).privateval signature = Signature.getInstance(signatureAlgorithm).run {initSign(privateKey)update(payload)sign()}val seq = DERSequence.fromByteArray(signature) as DLSequenceval r = bnUByteArrayToUByteArray((seq.getObjectAt(0) as ASN1Integer).value.toByteArray().toUByteArray(), 32)val s = bnUByteArrayToUByteArray((seq.getObjectAt(1) as ASN1Integer).value.toByteArray().toUByteArray(), 32)return r + s
}@OptIn(ExperimentalUnsignedTypes::class)
private fun byteArrayToHexString(byteArray: UByteArray): String {return byteArray.joinToString(separator = "") { it.toString(16).padStart(2, '0') }
}

iOS

static func secp256r1Key(name: String, requiresBiometry: Bool = false) throws -> SecKey {let flags: SecAccessControlCreateFlags = requiresBiometry ? [.privateKeyUsage, .userPresence] : .privateKeyUsagelet access =SecAccessControlCreateWithFlags(kCFAllocatorDefault,kSecAttrAccessibleWhenUnlockedThisDeviceOnly,flags,nil)!let tag = name.data(using: .utf8)!let attributes: [String: Any] = [kSecAttrKeyType as String           : kSecAttrKeyTypeEC,kSecAttrKeySizeInBits as String     : 256,kSecAttrTokenID as String           : kSecAttrTokenIDSecureEnclave,kSecPrivateKeyAttrs as String : [kSecAttrIsPermanent as String       : true,kSecAttrApplicationTag as String    : tag,kSecAttrAccessControl as String     : access] as [String : Any]]var error: Unmanaged<CFError>?guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else {throw error!.takeRetainedValue()}return privateKey
}static func getCompressedPublicKey(key: SecKey) throws -> Data {guard let publicKeyData = SecKeyCopyExternalRepresentation(SecKeyCopyPublicKey(key)!, nil) as? Data else {throw NSError()}let x = publicKeyData.dropFirst().prefix(32)let y = publicKeyData.subdata(in: Range(33...64))return Data([0x02 | (y.last! & 0x01)]) + x
}static func secp256r1Sign(name: String, payload: Data) -> Data {let key = secp256r1Key(name: name)var error: Unmanaged<CFError>?let asn1signature = SecKeyCreateSignature(key!, .ecdsaSignatureMessageX962SHA256, payload as CFData, &error)! as Datalet signature = try! ECSignature(asn1: asn1signature)return signature.r + signature.s
}

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

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

相关文章

Kubernetes(K8s):未来云原生应用的引擎

文章目录 Kubernetes的核心概念和架构为什么K8s是构建云原生应用的首选工具&#xff1f;云原生应用的好处和挑战容器编排的重要性&#xff1a;Docker和KubernetesKubernetes生态系统&#xff1a;核心组件和附加工具实际应用&#xff1a;企业如何在生产环境中使用K8s未来展望&am…

【VUE复习·2】@click 之事件处理与函数(可传参);@click 阻止事件冒泡应用场景;@click 多修饰符应用场景(高级)

总览 1.“事件处理”是什么 2.click 函数参数传递应用 3.click 阻止事件冒泡应用场景 4.click 多修饰符应用场景&#xff08;高级&#xff09; 一、“事件处理”是什么 1.概念 我们在和页面进行交互时&#xff0c;进行点击或滑动或其他动作时&#xff0c;我们操作的是 DOM …

MR混合现实在军事课堂教学中的应用演示

战场模拟&#xff1a;利用MR技术可以创建逼真的战场模拟环境&#xff0c;将学生置身于真实的战场场景中&#xff0c;可以体验和学习各种作战技巧和战术策略。学生可以通过佩戴MR头盔或眼镜&#xff0c;观察虚拟的场景&#xff0c;并与虚拟对象进行互动&#xff0c;如操作武器、…

深度学习|如何确定 CUDA+PyTorch 版本

对于深度学习初学者来说&#xff0c;配置深度学习的环境可能是一大难题&#xff0c;因此本文主要讲解CUDA; cuDNN; Pytorch 三者是什么&#xff0c;以及他们之间的依赖关系。 CUDA CUDA&#xff08;Compute Unified Device Architecture&#xff09;是由NVIDIA开发的用于并行计…

【C/C++笔试练习】——printf在使用%的注意事项、for循环语句的三个条件、运算符优先级、删除公共字符

文章目录 C/C笔试练习1.%符号在printf用作格式说明符的注意事项&#xff08;1&#xff09;输出%5.3s&#xff08;2&#xff09;判断%中小数点含义 2.for循环语句的三个条件&#xff08;3&#xff09;判断循环次数&#xff08;4&#xff09;判断循环次数 3.运算符优先级&#xf…

独立站引流,如何在Reddit进行营销推广?

Reddit是目前最被忽视却最具潜力的社交媒体营销平台之一&#xff0c;它相当于国内的百度贴吧&#xff0c;是美国最大的论坛&#xff0c;也是美国第五大网站&#xff0c;流量仅次于Google、Youtube、Facebook以及亚马逊。 如果会玩&#xff0c;Reddit也可以跟其他的社交媒体营销…

Spring 学习(九)整合 Mybatis

1. 整合 Mybatis 步骤 导入相关 jar 包 <dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><dependency>…

Django之初入门

一&#xff09;Django简介 1.简介 Django是一个开源的Python Web框架&#xff0c;它以简洁高效的方式帮助开发者构建复杂的Web应用程序。Django采用了MVC&#xff08;Model-View-Controller&#xff09;的架构模式&#xff0c;通过强大的工具和功能&#xff0c;提供了一套完整…

PHP 变动:PHP 8 版本下字符串与数值的弱比较

文章目录 参考环境声明弱比较隐式类型转换字符串连接数学运算布尔判断相等运算符 字符串与数值的弱比较字符串转化为数值的具体规则字符串与数值的弱比较一般情况科学计数法前缀 0E 与 0e PHP8 在字符串与数值的弱比较方面做出的改动数值字符串优化 参考 项目描述搜索引擎Bing…

数据库及分类详细介绍

目录 一、数据库详细介绍1、什么是数据库2、数据库的种类3、常见的数据库4、关系型数据库4.1、关系型数据库介绍4.2、关系型数据库的优缺点4.3、关系型数据库小结 5、非关系型数据库5.1、非关系数据库诞生的背景5.2、非关系型数据库的介绍5.3、非关系型数据库的优缺点5.4、非关…

js中的类型转换

原文地址 JavaScript 中有两种类型转换&#xff1a;隐式类型转换&#xff08;强制类型转换&#xff09;和显式类型转换。类型转换是将一个数据类型的值转换为另一个数据类型的值的过程。 隐式类型转换&#xff08;强制类型转换&#xff09;&#xff1a; 隐式类型转换是 Java…

NSSCTF

[SWPUCTF 2021 新生赛]gift_F12 在源代码界面找到了flag [SWPUCTF 2021 新生赛]jicao 源码 <?php highlight_file(index.php); include("flag.php"); $id$_POST[id]; $jsonjson_decode($_GET[json],true); if ($id"wllmNB"&&$json[x]"…

【Linux】Linux环境配置安装

目录 一、双系统&#xff08;特别不推荐&#xff09; 安装双系统的缺点&#xff1a; 安装双系统优点&#xff08;仅限老手&#xff09;&#xff1a; 二、虚拟机centos7镜像&#xff08;较为推荐推荐&#xff09; 虚拟机的优点&#xff1a; 虚拟机的缺点&#xff1a; ​ …

Molecular Cancer|CDK9抑制诱导表观遗传重编程,揭示了规避淋巴瘤耐药性的策略

细胞周期蛋白依赖性激酶&#xff08;CDK&#xff09;蛋白家族在细胞周期进程&#xff08;如CDK1/2/4/6&#xff09;和RNA转录&#xff08;如CDK7/8/9/11&#xff09;的调控中起着不可或缺的作用。由于染色体区域易位或基因扩增导致的CDKs表达失调与肿瘤发生有关。在淋巴瘤细胞中…

华为云云耀云服务器L实例评测 | 实例评测使用之硬件性能评测:华为云云耀云服务器下的硬件运行评测

华为云云耀云服务器L实例评测 &#xff5c; 实例评测使用之硬件性能评测&#xff1a;华为云云耀云服务器下的硬件运行评测 介绍华为云云耀云服务器 华为云云耀云服务器 &#xff08;目前已经全新升级为 华为云云耀云服务器L实例&#xff09; 华为云云耀云服务器是什么华为云云耀…

爬虫获取一个网站内所有子页面的内容

上一篇介绍了如何爬取一个页面内的所有指定内容&#xff0c;本篇讲的是爬去这个网站下所有子页面的所有指定的内容。 可能有人会说需要的内容复制粘贴&#xff0c;或者直接f12获取需要的文件下载地址一个一个下载就行了&#xff0c;但是如下图十几个一级几十个二级一百多个疾病…

华为云Stack的学习(七)

八、华为云Stack存储服务介绍 1.云硬盘EVS 云硬盘&#xff08;Elastic Volume Service&#xff0c;EVS&#xff09;&#xff0c;又名磁盘&#xff0c;是一种虚拟块存储服务&#xff0c;主要为ECS&#xff08;Elastic Cloud Server&#xff09;和BMS&#xff08;Bare Metal Se…

MySQL - order by排序查询 (查询操作 四)

功能介绍&#xff1a;order by&#xff1a;对查询结果进行排序&#xff0c;执行顺序在查询完结果执行&#xff08;比如where后&#xff09; 排序方式&#xff1a;ASC&#xff1a;升序&#xff08;默认&#xff0c;不用指定&#xff09; DESC&#xff1a;降序 语法&#x…

公司新招了个字节拿36K的人,让我见识到了什么才是测试扛把子......

5年测试&#xff0c;应该是能达到资深测试的水准&#xff0c;即不仅能熟练地开发业务&#xff0c;而且还能熟悉项目开发&#xff0c;测试&#xff0c;调试和发布的流程&#xff0c;而且还应该能全面掌握数据库等方面的技能&#xff0c;如果技能再高些的话&#xff0c;甚至熟悉分…