android 使用 .der 公钥验证文件签名

2024-01-06

我正在尝试验证文件的签名。我按照以下说明生成证书:

// generate a private key with size of 2048 bits
openssl genrsa -out private_key.pem 2048

// derive a public key from the above private key
openssl rsa -in private_key.pem -out public_key.pem -outform PEM -pubout

// iOS will not import PEM encoded data so it needs to be converted to DER encoded data
openssl rsa -pubin -inform PEM -outform DER -in public_key.pem -out public_key.der

// generate a self-signed certificate for testing
openssl req -new -x509 -key private_key.pem -out test_cert.pem -days 1095

// show the content of the original certificate
openssl x509 -in test_cert.pem -text -noout
// convert the certificate to DER format
openssl x509 -in test_cert.pem -outform der -out test_cert.der
// show the content of the new certificate
openssl x509 -in test_cert.der -inform der -text -noout

我用的例子是这个链接 https://web.archive.org/web/20160330194058/www.codealias.info/technotes/openssl_rsa_sign_and_verify_howto对一些数据进行哈希处理并验证一切是否正常(我执行了步骤 2 - 5)。

现在我正在尝试将 .der 文件、签名文件和数据文件放入 Android 应用程序中,并基本上验证一切是否正常。我没有收到任何错误,但我没有出错。下面是我编写的代码:

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.util.Base64;
import android.util.Log;
import android.widget.TextView;

import java.io.*;
import java.security.*;
import java.security.cert.CertificateFactory;
import java.security.cert.Certificate;

// Most of the below is taken from:
// http://www.herongyang.com/JDK/Digital-Signature-JcaVerify-Signature-Verification-Program.html
public class MyActivity extends Activity {

String input = Environment.getExternalStorageDirectory() + "/data.txt";
String signFile = Environment.getExternalStorageDirectory() + "/signature";
String signAlgo = "SHA1withRSA";
int keyFile = R.raw.test_cert_josh;
String TAG = "VERIFY";

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    TextView textView = (TextView) findViewById(R.id.textView);

    try {
        PublicKey pubKey = readPublicKey(keyFile);
        byte[] sign = readSignature(signFile);
        textView.setText(verify(input, signAlgo, sign, pubKey) + "");
    } catch (Exception e) {
        e.printStackTrace();
    }
}

PublicKey readPublicKey(int cert_id) throws Exception {
    InputStream in = MyActivity.this.getResources().openRawResource(cert_id);
    byte[] buff = new byte[4000];
    int bytesRead;
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    while((bytesRead = in.read(buff)) != -1) {
        out.write(buff, 0, bytesRead);
        Log.i(TAG, "bytes read: " + bytesRead);
    }

    byte[] publicKeyBytes = out.toByteArray();

    CertificateFactory cf = CertificateFactory.getInstance("X509");
    Certificate cert = cf.generateCertificate(new ByteArrayInputStream(publicKeyBytes));

    PublicKey pubKey = cert.getPublicKey();
    Log.i(TAG, "Public Key Info: ");
    Log.i(TAG, "Algorithm = " + pubKey.getAlgorithm());
    Log.i(TAG, "toString = " + pubKey.toString());
    return pubKey;
}

byte[] readSignature(String input) throws Exception {
    FileInputStream signStream = new FileInputStream(input);
    byte[] signBytes = new byte[signStream.available()];
    signStream.read(signBytes);
    signStream.close();
    return  signBytes;
}

boolean verify(String input, String algorithm, byte[] sign, PublicKey pubKey) throws Exception {
    Signature sg = Signature.getInstance(algorithm);
    sg.initVerify(pubKey);
    Log.i(TAG, "Signature Object Info: ");
    Log.i(TAG, "Algorithm = "+sg.getAlgorithm());
    Log.i(TAG, "Provider = "+sg.getProvider());

    FileInputStream in = new FileInputStream(input);
    byte[] buff = new byte[in.available()];
    in.read(buff);

    sg.update(buff);

    boolean ok = sg.verify(sign);
    Log.i(TAG, "Verify Processing Info: ");
    Log.i(TAG, "Verification result = "+ok);
    return ok;
}
}

我读过的所有内容都表明我的代码是正确的。我认为有关获取公钥的部分是正确的,因为模数与实际 .der 文件中的模数相匹配。

请帮忙!

EDIT:我认为这与我读取签名文件或数据文件的方式有关。我很确定我正确地获取了有关公钥的所有信息,因为我打印了有关它的附加信息并且它与openssl 输出

EDIT根据下面 Nikolay 的建议,我尝试使用以下代码在 Android 应用程序中签署与我在 openssl 中登录的相同数据:

// testing code to sign it myself
// read the data file in
FileInputStream dataStream = new FileInputStream(input);
byte[] dataBytes = new byte[dataStream.available()];
dataStream.read(dataBytes);
dataStream.close();

// hash the data file, like i do with openssl
// per Nikolay's comments, this is not needed
MessageDigest digest = MessageDigest.getInstance("SHA-1");
// digest.update(dataBytes, 0, dataBytes.length);
// dataBytes = digest.digest();
Log.i(TAG, "data from file: " + new String(dataBytes));

// read the private key in
FileInputStream fis = new FileInputStream(Environment.getExternalStorageDirectory() + "/phaero/private_key.pem");
byte[] keyBytes = new byte[fis.available()];
fis.read(keyBytes);
fis.close();

// clean up the private key and decode it
String temp = new String(keyBytes);
Log.i(TAG, "private key: " + temp);
String privKeyPEM = temp.replace("-----BEGIN RSA PRIVATE KEY-----\n", "");
privKeyPEM = privKeyPEM.replace("-----END RSA PRIVATE KEY-----", "");
byte[] decoded = Base64.decode(privKeyPEM.getBytes(), Base64.DEFAULT);

// create the private key object from the private key data
PKCS8EncodedKeySpec private_spec = new PKCS8EncodedKeySpec(decoded);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey privateKey =  kf.generatePrivate(private_spec);

// set up for signing
Signature signer = Signature.getInstance(signAlgo);
signer.initSign(privateKey);
signer.update(dataBytes, 0, dataBytes.length);

// sign, and hash again so i can compare against openssl output
byte[] signed = signer.sign();
digest.update(signed, 0, signed.length);
Log.i(TAG, new BigInteger(1, digest.digest()).toString(16));

快速注意:在 Jelly Bean 中使用上述代码,您必须在创建 KeyFactory 时指定“BC”。

然后我对签名结果进行哈希处理,看看它是否与使用 openssl 生成的签名文件的哈希值相匹配,但它们不匹配..所以我不知道这意味着什么,但我知道这意味着什么!我假设在 openssl 中创建签名文件时需要指定某种附加选项?

EDIT:

根据下面 Nikolay 的评论,我将测试代码更新为不签名,但是在 java 中创建的签名的哈希值仍然与使用 openssl 创建的签名文件的哈希值不匹配...不知道出了什么问题,Java、OpenSSL 还是我。


经过@NikolayElenkov 的大量帮助后,我终于弄清楚出了什么问题。尝试不同的谷歌搜索,我偶然发现这个计算器问题 https://stackoverflow.com/questions/9951559/difference-between-openssl-rsautl-and-dgst,那家伙说你可以运行两个不同的签名命令。当我创建所有签名时,我使用了上面链接的内容:

// create a hash
echo 'data to sign' > data.txt
openssl dgst -sha1 < data.txt > hash
// sign it
openssl rsautl -sign -inkey private.pem -keyform PEM -in hash  > signature
// verify it
openssl rsautl -verify -inkey public.pem -keyform PEM -pubin -in signature > verified
diff -s verified hash

从我今天发现的帖子中,我尝试了:

openssl dgst -sha1 -sign privateKey.pem -out signature1 someInputFile

正如该人所说,这会创建一个不同的签名文件。这是我需要的 Android 代码!因此,要验证这一点,答案是我需要更改生成签名文件的方式! (如果没有@NikolayElenkov,我不会走到这一步,非常感谢!)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

android 使用 .der 公钥验证文件签名 的相关文章

  • 如何在android中实现触摸平滑图像橡皮擦?

    我已经从 API 演示中看到了finturePaint java 我想实现触摸平滑橡皮擦 通过在android中触摸移动来擦除部分图像 FingerPaint 告诉我要实现这个 mPaint setXfermode new PorterDu
  • 如何从 SDK 实现每个会话的 Google Places 自动完成功能?

    是否可以从 Android 和 iOS 应用程序的 place sdk 实现基于会话的自动完成 根据 6 月 11 日生效的新 Google 地图框架定价 对自动完成的请求可以分为基于击键 会话的请求 我找不到描述实施步骤的文档 除了这个参
  • 我在布局上看不到任何 FirebaseRecyclerAdapter 项目

    我试图将数据从 Firebase 数据库检索到我的布局 但我看不到任何项目FirebaseRecyclerAdapter在布局中 请帮忙 我按照一个教程展示了如何做到这一点 当我运行应用程序时 我没有看到任何项目 但我可以滚动 public
  • Android Q:file.mkdirs() 返回 false

    我们有一个应用程序 使用外部存储来存储一些临时文件 图像 二进制数据 该代码已经运行了几年 直到最近才发生重大变化 在 Android Q 上它不起作用 File f new File Environment getExternalStor
  • 如何使用 Google Maps for Android V2 处理地图移动结束?

    我想在地图中心更改后立即对地址进行地理编码 如何使用新的 Android 版 Google 地图 V2 处理地图移动 我说的是用户用手指拖动地图的情况 查看新的地图 API Override public void onMapReady G
  • 通过 WhatsApp 发送消息

    由于我发现了一些较旧的帖子 表明 Whatsapp 不支持此功能 我想知道是否发生了变化 以及是否有办法打开与我通过意图发送的号码进行 Whatsapp 聊天 UPDATE请参阅https faq whatsapp com en andro
  • Bitmap.getPixels() 中的 IllegalArgumentException

    我想将数据从位图复制到int using getPixels 这是我当前的代码 int pixels new int myBitmap getHeight myBitmap getWidth myBitmap getPixels pixel
  • 如何重定向到 instagram://user?username={username}

    我的 html 页面上有这个链接 可以在特定用户上打开 Instagram 应用程序 a href Link to Instagram Profile a 我一直在寻找自动运行 url instagram user username USE
  • Android:后台Activity可以执行代码吗?

    后台的活动是否被视为 正在运行 并且可以执行代码 还是处于挂起状态 他们暂停了 活动生命周期 http developer android com reference android app Activity html ActivityLi
  • Android 手机作为 GSM 调制解调器在 PC 上发送/接收短信?

    是否可以将 Android 移动设备用作 PC 上的 GSM 调制解调器 我正在 net下开发应用程序来发送 接收短信等 现在我想通过 USB 将我的 Android 设备连接到我的 PC 并将其用作 GSM 调制解调器来与其通信 这里是参
  • 从 BroadcastReceiver 类调用活动方法

    我知道我可以做一个内部接收器类来调用接收器中的任何方法 但我的主要活动太大了 要做的事情也很多 因此 我需要一个扩展广播接收器的类 但它不是内部类 并且可以从我的主要活动中调用一种方法 我不知道是否可能 但我的活动是家庭活动和 single
  • Android Studio 缓慢的增量构建

    我已经完成了许多步骤来完善我们的构建系统 those https stackoverflow com questions 16775197 building and running app via gradle and android st
  • Android 如何将总天数准确更改为年、月、日?

    我正在做一个应用程序 该应用程序与根据给定的生日日期输入获取一个人的年龄有关 为此 我从下面的代码中获取从该日期到当前日期的总天数 String strThatDay 1991 05 10 SimpleDateFormat formatte
  • 在命令行上卸载 Android SDK 的选定部分

    这与 卸载旧的 Android SDK 版本 https stackoverflow com questions 15182377 uninstall old android sdk versions 除非我想在无头 Linux CI 服务
  • 找不到符号 NOTIFICATION_SERVICE?

    package com test app import android app Notification import android app NotificationManager import android app PendingIn
  • 插件“Android Bundle Support”不兼容

    大家好 自从上次更新以来 当我启动 android studio 时 我遇到了一个非常奇怪的错误 我有这个错误 插件错误 插件 Android Bundle Support 不兼容 直到构建 AI 195 SNAPSHOT 我在网上找不到任
  • 如何使用 AccessibilityService 在 Android 中模拟按键

    我正在编写一个辅助服务 我一直在尝试在应用程序上进行一些自动搜索 我使用accessibilityservice action paste来填充EditText 然后我需要模拟软键盘上的按键 但我不知道如何做 你们能帮我一下吗 你可以尝试A
  • 我的应用程序中的后退按钮出现问题[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我想在手机关闭时清除共享首选项值 你
  • Android 后台倒计时器

    我有一个 Android 应用程序 它管理一个倒计时器 类 CountDownTimer 它显示在应用程序屏幕中 以显示到达 00 00 还剩多少时间 我现在的问题是 当我按主页按钮或启动另一个应用程序时 应用程序 计时器不会在后台运行 所
  • 有没有任何代码可以在android中设置壁纸而无需裁剪和缩放?

    我正在创建一个画廊应用程序 我的第一个应用程序 这是我的代码 Bitmap bmd BitmapFactory decodeStream is try getApplicationContext setWallpaper bmd catch

随机推荐

  • 对需要带有模式的整数的元素使用 JAXB 生成的类

    我的 XML 架构中有一个元素定义如下
  • python QTconsole 的数据隐藏

    目前我正在制作一个图像身份验证项目 其中我需要借助密钥来验证图像 我将钥匙作为raw input用户通过 IPython 控制台 我想隐藏正在输入的密钥 预期结果 Enter the key or Enter the key nothing
  • pandas 将函数应用于多列和多行

    我有一个数据帧 其行和列 xpos ypos 中具有连续的像素坐标 我想计算连续像素之间每条路径的角度 以度为单位 目前我有下面介绍的解决方案 该解决方案工作正常 并且对于我的文件大小来说足够快 但迭代所有行似乎不是 pandas 的方式
  • 如何在大型项目中进行单元测试

    我们有一个项目开始变大 我们需要在开始重构时开始应用单元测试 将单元测试应用于已存在的项目的最佳方法是什么 我 在某种程度上 习惯从头开始做这件事 我将测试与第一行代码一起编写 当功能已经到位时 我不确定如何开始 我应该开始为存储库中的每个
  • MongoDB NumberLong 和简单 Integer 之间的区别?

    MongoDB 中数据类型 double NumberLong NumberInt 或简单 Integer 之间的主要区别是什么 大小 速度等 如果我想保存一个小的固定数字 0 到 1000 之间的数字 我应该使用哪种数据类型 数字整数 默
  • 如何在引导日期选择器中添加最大日期

    我需要为日期选择器添加 maxdate 并且我正在使用这个插件 cdnjs cloudflare com ajax libs bootstrap datepicker 1 3 0 js bootstrap datepicker min js
  • omp 并行与 omp 并行 for

    这两者有什么区别 A pragma omp parallel pragma omp for for int i 1 i lt 100 i B pragma omp parallel for for int i 1 i lt 100 i 这些
  • 在springboot应用程序中配置mvc异步任务执行器

    我试图覆盖 SpringBoot SpringMVC 应用程序中 RequestMappingHandlerAdapter bean 使用的默认任务执行器 javadocs 建议替换默认值的使用 但没有给出任何关于如何执行此操作的指示 我也
  • 如何获取整个矩阵、数组或数据帧的平均值、中位数和其他统计数据?

    我知道这是一个基本问题 但由于某种奇怪的原因我无法找到答案 我应该如何在整个数组 矩阵或数据帧上应用基本统计函数 如平均值 中位数等 以获得唯一的答案 而不是行或列上的向量 由于这个问题出现得相当频繁 我将更全面地对待这个问题 包括 等等
  • Spring MVC 3.1 异常:Errors/BindingResult 参数预计紧随模型属性参数之后

    我升级到 Spring 3 1 1 RELEASE 现在我在以下方法中遇到异常 RequestMapping method RequestMethod POST params finish public ModelAndView doPos
  • 为什么这个 Java String.replaceAll() 代码不起作用?

    我以前在 Java 中使用过 string replaceAll 没有遇到任何问题 但我对这个感到困惑 我认为它会正常工作 因为没有 或 字符 这是我正在尝试做的事情 String testString constant float win
  • 如何使用 babel 或 webpack 在 ES6 导入/导出模块中使用 Node.js CommonJS 模块?

    如果这是重复的 我很抱歉 我使用搜索工具仔细查找 但没有任何结果 有人知道如何转译 Node js CommonJS 模块以便它们可以在 ES6 导入 导出项目中使用吗 我知道有 babel plugin transform modules
  • 使用 C++ 类的架构 x86_64 的未定义符号

    我已阅读有关此主题的其他问题 但仍不知道如何解决我的问题 预先感谢您的帮助 我的错误是 体系结构 x86 64 的未定义符号 Record Record std 1 vector std 1 allocator gt std 1 alloc
  • Android:如何知道 MediaPlayer 是否已暂停?

    MediaPlayer isPlaying 不允许知道是否MediaPlayer已停止或暂停 如何知道是暂停了还是没有停止 Thanks 执行此操作的一种方法是检查媒体播放器是否未播放 暂停 并检查它是否位于起始位置 1 以外的位置 Med
  • 在线条末端绘制标签

    我有以下数据 temp dat完整数据请参见尾注 Year State Capex 1 2003 VIC 5 356415 2 2004 VIC 5 765232 3 2005 VIC 5 247276 4 2006 VIC 5 57988
  • 在 SQL 查询中显示串联值

    我想将我的第一个 sql 查询与下面显示的 id pr 值的表类型连接起来 ID PR 值会重复 我想显示 ident st 列中与相同 id pr 和 rodz st 值用逗号分隔符连接的所有值 例如 显示 rodz st DZE 和 i
  • 在 MATLAB 中交换两个元素的性能

    纯粹作为实验 我在 MATLAB 中编写排序函数 然后通过 MATLAB 分析器运行这些函数 我发现最令人困惑的方面是与交换元素有关 我发现交换矩阵中两个元素的 官方 方式 self Data i1 i2 self Data i2 i1 运
  • 对于 Electron 来说,结合 Node.js 和 Chromium 上下文意味着什么?

    In 一篇博文 http maxogden com electron fundamentals html作者提到 Electron 将 Node 和 Chromium 组合成一个 单一上下文 这意味着我们不必使用 Browserify 来转
  • SqlBulkCopy 和实体框架

    我当前的项目由 3 个标准层组成 数据 业务和表示 我想使用数据实体来满足我的所有数据访问需求 该应用程序的部分功能是需要将平面文件中的所有数据复制到数据库中 文件不是很大 所以我可以使用 SqlBulkCopy 我发现了几篇关于 NET
  • android 使用 .der 公钥验证文件签名

    我正在尝试验证文件的签名 我按照以下说明生成证书 generate a private key with size of 2048 bits openssl genrsa out private key pem 2048 derive a