Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/345.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/css/41.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将java双精度编码为asn1实{符号、尾数、基、指数}_Java_Asn.1 - Fatal编程技术网

将java双精度编码为asn1实{符号、尾数、基、指数}

将java双精度编码为asn1实{符号、尾数、基、指数},java,asn.1,Java,Asn.1,我已经实现了自己的ASN.1框架,最后一项是将Java Double编码为ASN.1 Real。第一个链接是我的库,然后是ASN.1 Reals上规范的链接。我的问题在我的encodeDoubleValue中访问正确的尾数。救命啊 https://github.com/ZiroZimbarra/ASN1 我在Reals测试中的代码如下所示: testRealBytes(new byte[] {9, 5, (byte) 0x80, (byte) 0xFE, (byte) 0x55, (byte

我已经实现了自己的ASN.1框架,最后一项是将Java Double编码为ASN.1 Real。第一个链接是我的库,然后是ASN.1 Reals上规范的链接。我的问题在我的encodeDoubleValue中访问正确的尾数。救命啊

https://github.com/ZiroZimbarra/ASN1

我在Reals测试中的代码如下所示:

testRealBytes(new byte[] {9, 5, (byte) 0x80, (byte) 0xFE, (byte) 0x55, (byte) 0x55, (byte) 0x55}, 1398101.25);
这是我的测试实现,我的问题出现在第三行代码的编码上

    private void testRealBytes(byte[] bytes, Object testObj) throws IOException, InstantiationException, IllegalAccessException {
    Object obj = (Double) ASN1InputStream.decode(bytes);
    assertTrue(obj.equals(testObj));
    byte[] newBytes = ASN1OutputStream.encodeObject(obj);
    assertTrue(Arrays.equals(bytes, newBytes));
}
以下是我的编码值方法:

    public void encodeDoubleValue(Double doubleObj, ASN1OutputStream derStream) throws IOException {
    if(doubleObj == 0) {return; }
    if(doubleObj == Double.POSITIVE_INFINITY) { derStream.write(0x40); return; }
    if(doubleObj == Double.NEGATIVE_INFINITY) { derStream.write(0x41); return; }
    long bits = Double.doubleToLongBits(doubleObj);
    long mantissa = (bits & 0x000fffffffffffffL);
    int exponent = Integer.valueOf(Long.valueOf(((bits & 0x7FF0000000000000L) >> 52) - 1023).toString());
    int base = 2;
    byte signByte = (byte) (((bits & 0x8000000000000000L) > 1) ? 0x40 : 0x00);
    ASN1OutputStream exponentStream = derStream.newStream();
    new ASN1IntegerType().encodeValue(exponent, exponentStream);
    byte[] exponentBytes = exponentStream.toByteArray();
    switch(exponentBytes.length) {
        case 1: 
            derStream.write(0x80 | (byte) signByte | 0x00);
            break;
        case 2:
            derStream.write(0x80 | (byte) signByte | 0x01);
            break;
        case 3:
            derStream.write(0x80 | (byte) signByte | 0x02);
            break;
        default:
            derStream.write(0x80 | (byte) signByte | 0x03);
            derStream.write(exponentBytes.length);
            break;
    }
    derStream.write(exponentBytes);

    byte[] leftBytes = Long.toUnsignedString(mantissa, 16).getBytes();
    int length = leftBytes.length;
    byte[] mantissaBytes = new byte[length];
    for(int i = 0; i < length; i++) {
        mantissaBytes[i] = leftBytes[length - i - 1];
    }
    for(byte b : mantissaBytes) {
        derStream.write(b);
    }
}
而不是它应该是什么

[9, 5, -128, -2, 85, 85, 85]

正如Kevin所评论的,除了使用字符(BER/DER仅对base=10使用)而不是位之外,还使用了完全没有意义的反向操作,您的错误是:

  • Java(以及最流行的CPU)使用的IEEE-then ISO/IEC浮点方案与大多数其他方案一样,在“尾数”(更好,有效位)的左侧有一个隐含的二进制/基数点,而不是在BER/DER的右侧,并且在该隐含点的左侧有一个“隐藏”1位

  • DER(但不是BER)需要规范化尾数(零除外,它已经是特殊情况),因此它的最低有效位是1;对于base=2,这只需要调整指数,但8或16也需要比例因子

此外,您不需要使用
ASN1OutputStream
来编码整数,因为Java的内置
BigInteger.toByteArray()
已经生成了规范的大端二补,并且您实际上不需要处理大于2个八位字节的指数长度,因为它们永远不会出现在IEEE-ISO/IEC值中。(如果需要
BigDecimal
值或类似值,则可能需要它们。)

以下代码生成正确的预期值(不包括标记和长度):

double d=1398101.25d;
ByteArrayOutputStream str=新建ByteArrayOutputStream();
//对于演示,根据需要使用实际输出
长位=双。双或长位(d);

int signByte=(int)(位>>(63-6))&(1我在调用toUnsignedString(尾数,16)的基础上修改为基数16。我建议你问一些具体的问题,并添加一些注释来解释你在做什么。我不太清楚你是如何遵循DER规范的。最突出的一点是,你在那里使用toUnsignedString做什么?我不知道你为什么要将尾数转换为字符串表示,然后使用这些字符串表示racter并对相应的字节进行编码。您应该使用base 2进行编码。也许您正在尝试使用base 10。我不知道。更好的
getBytes(StandardCharsets.US\u ASCII)
但在那一点上,逻辑丢失了。有一些Long.reverse和reverseebytes。还有ByteBuffer。谢谢你的回答!我通过了测试,现在我的Squeak加密ASN1框架到Java的端口已经完成。现在,我要继续使用Parrotalk,我的2048位密钥协商连接框架。我必须在某个地方分享我的消息。这是一个很好的地方,就像你帮助完成我的ASN1编码器一样。我完成了我的会合工作,然后潜入我的密码、ivSequence和mac,所有这些都工作了。我现在有了一个Squeak版本、一个Pharo版本和一个Java版本,讨论我的ParrotTalk协议[1].在基于ASN.1的RSA公钥、密码和编码器选择、diffie-hellman参数和流量签名的会合和交换之后,在所有三个系统中加密和解密数据。它完成并构建了一个加密堆栈,其中包含MAC移民、解密、MAC海关验证、解码和来自会话的事件广播在到达的数据上。Hello world在每个实现中传递。现在我将看看是否可以在Pharo和Java之间传递数据。我修复了Java实现,只对已传递的asn1编码头进行签名。Pharo/Squeak中的签名匹配。Java中发送“再见”仍然是一个问题。因此…Pharo/Squeak/Java走到了一起。
[9, 5, -128, -2, 85, 85, 85]
    double d = 1398101.25d;
    ByteArrayOutputStream str = new ByteArrayOutputStream();
    // for demo, use real output as needed

    long bits = Double.doubleToRawLongBits(d);
    int signByte = (int)(bits>>(63-6))&(1<<6) | (1<<7);
    // shift to the correct place to start with, and pre-add bit 8
    int exponent = ((int)(bits>>52)&0x7FF)-(1023+52);
    // don't need to box/unbox to do arithmetic
    long mantissa = (bits&0xFFFFFFFFFFFFFL) | (1L<<52);
    // add the hidden bit
    while( (mantissa&1)==0 ){ mantissa>>=1; exponent++; }
    // normalize
    byte[] exptbytes = BigInteger.valueOf(exponent).toByteArray();
    if(exptbytes.length<3) str.write(signByte|(exptbytes.length-1)); 
    else{ str.write(signByte|3); str.write(exptbytes.length); }
    // only the if branch is actually needed 
    str.write (exptbytes);
    str.write (BigInteger.valueOf(mantissa/*>>scale*/).toByteArray());

    System.out.println(Arrays.toString(str.toByteArray()));
    // for demo