X.509 证书的 Java 1.7 主题哈希 OpenSSL 1.0+ 兼容

2024-04-16

我已经为此苦苦挣扎了几天。我正在开发一个在嵌入式 Linux 环境中运行的 Java 1.7 应用程序。 OpenSSL 不可用,我无法控制设备上操作系统映像中的内容。我需要计算自签名 X.509 证书的主题哈希,生成与 OpenSSL 1.0+ 相同的结果。这个现有的答案让我开始:

新的主题散列 openssl 算法有所不同 https://stackoverflow.com/questions/19237167/the-new-subject-hash-openssl-algorithm-differs

我的测试应用程序的代码如下所示。我的计算适用于主题名称仅包含 CN 值的证书,但不适用于指定了任何其他主题组件(OU、O、L、ST 或 C)的证书。对于这些证书,整个主题的哈希值(减去介绍序列)不匹配。根据上面的答案,我提取了每个组件(使用 getObjectAt( ) 方法)并单独对每个组件进行哈希处理(没有乐趣),颠倒它们的顺序并对它们全部进行哈希处理(没有乐趣),以及其他一些变体主题。我一直在努力避免下载 OpenSSL 源代码并运行它,这样我就可以检查中间结果并看看哪里出了问题,这会是我担心的更耗时的工作。也许做过这件事的人可以提供一些指导。

private static void getSubjectHash( X509Certificate x509Cert )
{
    try {
        // get the subject principal
        X500Principal x500Princ = x509Cert.getSubjectX500Principal( );

        // create a new principal using canonical name (order, spacing, etc.) and get it in ANS1 DER format
        byte[] newPrincEnc = new X500Principal( x500Princ.getName( X500Principal.CANONICAL ) ).getEncoded( );

        // read it in as an ASN1 Sequence to avoid custom parsing
        ASN1InputStream aIn = new ASN1InputStream( newPrincEnc );
        ASN1Sequence seq = (ASN1Sequence) aIn.readObject( );

        List<byte[]> terms = new ArrayList<>( );
        int finalLen = 0;
        int i = 0;

        // hash the encodables for each term individually and accumulate them in a list
        for ( ASN1Encodable asn1Set : seq.toArray( ) ) {
            byte[] term = ( (ASN1Set) asn1Set ).getEncoded( );
            terms.add( term );
            finalLen += term.length;

            // digest the term
            byte[] hashBytes = truncatedHash( getDigest( term ), 4 );
            printByteArray( String.format( "hash of object at %d:", i++ ), hashBytes );

            System.out.println( "" );
        }


        // hash all terms together in order of appearance
        int j = 0;
        byte[] finalEncForw = new byte[finalLen];
        for ( byte[] term : terms )
            for ( byte b : term )
                finalEncForw[j++] = b;

        // digest and truncate
        byte[] hashBytes = truncatedHash( getDigest( finalEncForw ), 4 );

        printByteArray( "hash of all terms in forward order", hashBytes );
        System.out.println( "" );


        // hash all terms together in reverse order
        j = 0;
        byte[] finalEncRev = new byte[finalLen];
        for ( int k = terms.size( ) - 1; k >= 0; --k )
            for ( byte b : terms.get( k ) )
                finalEncRev[j++] = b;

        // digest and truncate
        hashBytes = truncatedHash( getDigest( finalEncRev ), 4 );

        printByteArray( "hash of all terms in reverse order", hashBytes );
    }
    catch ( Exception ex ) {
        throw new RuntimeException( "uh-oh" );
    }
}

private static byte[] getDigest( byte[] toHash )
{
    MessageDigest md;

    try {
        md = MessageDigest.getInstance( "SHA1" );
    }
    catch ( NoSuchAlgorithmException nsa ) {
        throw new RuntimeException( "no such algorithm" );
    }

    return md.digest( toHash );
}

private static byte[] truncatedHash( byte[] hash, int truncatedLength )
{
    if ( truncatedLength < 1 || hash.length < 1 )
        return new byte[0];

    byte[] result = new byte[truncatedLength];

    for ( int i = 0; i < truncatedLength; ++i )
        result[truncatedLength - 1 - i] = hash[i];

    return result;
}

private static void printByteArray( String name, byte[] bytes )
{
    System.out.println( name + " length=" + String.valueOf( bytes.length ) );
    for ( byte b: bytes ) {
        System.out.print( String.format( "%02X ", Byte.toUnsignedInt( b ) ) );
    }

    System.out.println( );
}

好的,现在是管道胶带。这似乎适用于我可测试的所有证书。这是 getSubjectHash 方法的重写版本:

private static void getSubjectHash( X509Certificate x509Cert )
{
    try {
        // get the subject principal
        X500Principal x500Princ = x509Cert.getSubjectX500Principal( );

        // create a new principal using canonical name (order, spacing, etc.) and get it in ANS1 DER format
        byte[] newPrincEnc = new X500Principal( x500Princ.getName( X500Principal.CANONICAL ) ).getEncoded( );

        // read it in as an ASN1 Sequence to avoid custom parsing
        ASN1InputStream aIn = new ASN1InputStream( newPrincEnc );
        ASN1Sequence seq = (ASN1Sequence) aIn.readObject( );

        List<byte[]> terms = new ArrayList<>( );
        int finalLen = 0;
        int i = 0;

        // hash the encodables for each term individually and accumulate them in a list
        for ( ASN1Encodable asn1Set : seq.toArray( ) ) {
            byte[] term = ( (ASN1Set) asn1Set ).getEncoded( );
            term[9] = 0x0c; // change tag from 0x13 (printable string) to 0x0c
            terms.add( term );
            finalLen += term.length;

            // digest the term
            byte[] hashBytes = truncatedHash( getDigest( term ), 4 );
            printByteArray( String.format( "hash of object at %d:", i++ ), hashBytes );

            System.out.println( "" );
        }


        // hash all terms together in order of appearance
        int j = 0;
        byte[] finalEncForw = new byte[finalLen];
        for ( byte[] term : terms )
            for ( byte b : term )
                finalEncForw[j++] = b;

        // digest and truncate
        byte[] hashBytes = truncatedHash( getDigest( finalEncForw ), 4 );

        printByteArray( "hash of all terms in forward order", hashBytes );
        System.out.println( "" );

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

X.509 证书的 Java 1.7 主题哈希 OpenSSL 1.0+ 兼容 的相关文章

随机推荐

  • 带水平滚动的 C3 / D3 条形图

    我正在创建一个 c3 条形图 其中每个条形代表在给定的一周内加入某个计划的人数 数据只是一个对象数组 其中包含 week of people week of people 等 理想情况下 我希望图表中显示最近 6 周的数据 但我希望能够水平
  • Windows 上 Python 3.4 中的 Tkinter 在退出时不会将内部剪贴板数据发布到 Windows 剪贴板

    我使用以下代码将小脚本的结果放置在剪贴板中 from tkinter import Tk r Tk r withdraw r clipboard clear r clipboard append Result 它在 Python 3 3 5
  • 如何使用 Celery、RabbitMQ 和 Django 确保每个用户的任务执行顺序?

    我正在运行 Django Celery 和 RabbitMQ 我想要实现的是确保与一个用户相关的任务按顺序执行 具体来说 一次执行一个 我不希望每个用户执行任务并发 每当为用户添加新任务时 它应该取决于最近添加的任务 如果此类型的任务已为此
  • 和发动机施加力

    有谁知道为什么 applyforce 只适用于我的精灵之一 此外 当我按下其他精灵时 它也会对单个精灵施加力 nextTile 方法工作正常 enter code herecom martynnorman jude 包 作者尼古拉斯 格拉姆
  • css - 垂直滚动条删除

    下面是带有左右附加图像的菜单行的代码 我需要这样的行为 当屏幕宽度的分辨率从 960px 到 1398px 时 左右 div 同时隐藏 这段代码完全符合我的要求 问题是 在低屏幕宽度 960px 到 1398px 上 它会向浏览器添加水平滚
  • Facebook Messenger Bot 可以与群组中的两个或更多人聊天吗?

    所有消息机器人一次只与一名用户直接交互吗 机器人可以加入两人或多人组成的群组并与他们交谈吗 目前 Facebook Messenger 机器人只能在一对一的基础上工作 原因之一可能是隐私 Facebook 在在群组环境中推出机器人之前非常谨
  • 快速获取当前设备在 wifi 和蜂窝网络中的 IP 地址

    func getIPAddress gt String var address String var ifaddr UnsafeMutablePointer
  • 使用 PowerShell 删除文本文件的顶行

    我试图在导入之前删除大约 5000 个文本文件的第一行 我对 PowerShell 还很陌生 所以不确定要搜索什么或如何解决这个问题 我当前使用伪代码的概念 set content file get content unless line
  • 使用 jQuery 和 Select2 时“按键”事件无法正常工作

    我有一个论坛 我在其中更改选项卡的功能以进入 当用户按下 Enter 下一个输入字段时获得焦点并以某种方式 iImanage 打开 select2 选择框focusin事件 因此选择 2 框打开 但是 当我选择该值并在 selec2 选择框
  • Laravel/Symfony:无法加载“app”配置文件

    升级我的家园并安装我的软件包后 我遇到了一个奇怪的错误 通话中php artisan输出如下 In LoadConfiguration php line 68 Unable to load the app configuration fil
  • opencv边界框问题

    我有一个图像需要在周围绘制一个边界框 我正在尝试使用本文底部的代码 我遇到的问题是我尝试模糊蓝色框形状以删除其细节 例如 cv2 blur img 20 20 但模糊图像似乎没有足够好的边缘来生成边界框 我发现 如果我将下面的代码与具有与下
  • Spring Java 应用程序找不到密钥库文件

    我正在尝试设置一个简单的 Spring 应用程序来使用 SSL 并将其托管在 Digital Ocean 上 为什么我的应用程序找不到密钥库文件 我设置的 Droplet 基于 Ubuntu 18 04 我使用 Letscrypt 来获取证
  • WCF net.tcp 传输安全 - 如何在客户端上禁用服务器证书验证

    我正在使用 WCF 进行一些测试 目前我们有以下服务器设置 简化的配置
  • 在 MSBuild 中将字符串构建为基本字符串 n 次的串联

    我在 MSBuild 的属性中有一个数字 n 我还有一个字符串 Str 需要重复 n 次才能获得最终字符串 即重复 Str n 次 例如 如果n为3 Str为 abc 我想要获取的是 abcabcabc 由于无法在 MSBuild 中循环
  • 如何在 Windows 上为 ruby​​ 安装 PCAP

    这肯定是一个相对较新的问题 但我仍然陷入困境 我知道有一个简单的解决方案 我已经进行了一些谷歌搜索 但找不到确切的答案 这是我得到的错误 C Ruby193 include ruby 1 9 1 i386 mingw32 gt gem in
  • 将一个 div 置于另一个 div 之上

    我向我的网络应用程序添加了一个登陆页面 因此当它从服务器加载数据时 登陆页面会显示加载图像和描述 div class map view div class loading screen img src img loading boys gi
  • 在 Web.Config 文件外部存储 SMTP

    一段时间以来 我一直将连接和应用程序设置存储在外部文件中 并仅通过 web config 引用该文件 这非常有效 因为它允许我保留单独的连接字符串和应用程序设置 这真的很方便 因为我发现在开发过程中我经常会对 webconfig 进行许多更
  • CreateRemoteThread 32->64 和/或 64->32

    我需要一种在 x64 窗口中 CreateRemoteThread 到 64 和 32 位进程的方法 我已经弄清楚了如何找到目标进程的指令集 如何在目标进程中为汇编雪橇分配内存 并且我几乎已经弄清楚如何处理地址空间随机化 当远程进程的指令集
  • 为什么我的原型函数不返回实例的属性?

    我有一个简单的 JavaScript 对象 函数 myClass x y this x x this y y 和一个原型函数 myClass prototype myfunction function console log this x
  • X.509 证书的 Java 1.7 主题哈希 OpenSSL 1.0+ 兼容

    我已经为此苦苦挣扎了几天 我正在开发一个在嵌入式 Linux 环境中运行的 Java 1 7 应用程序 OpenSSL 不可用 我无法控制设备上操作系统映像中的内容 我需要计算自签名 X 509 证书的主题哈希 生成与 OpenSSL 1