Base64解码值损坏的字符串(Java),

时间:2015-10-28 01:11:14

标签: java jsp asp-classic character-encoding base64

我正在从base64 encoded string页面向Classic ASP页面发送JSP。在编码之前,字符串是RC4加密的。

现在,我观察到,在ASP页面内,使用base64对字符串进行编码和解码可以正常工作。但是,base64 decoded string页面上的JSP不正确。我也尝试在Eclipse中解码字符串并获得相同的结果。它似乎与字符编码类型有关,但我正在努力确定究竟是什么问题。

  • base64编码字符串: yOBIc4FY
  • base64解码后的字符串(来自ASP页面):ÈàHsX(正确)
  • base64解码后的字符串(来自JSP页面和Eclipse):ÈàHs?X (不正确)

Java / JSP代码:

import org.apache.commons.codec.binary.Base64;

String base64String = "yOBIc4FY";

byte[] decodedBase64Byte = Base64.decodeBase64(base64String);

// ÈàHs?X
decodedBase64String = new String(decodedBase64Byte, "ISO-8859-1");

// ÈàHs?X
decodedBase64String = new String(decodedBase64Byte, "windows-1252");

// ??Hs?X
decodedBase64String = new String(decodedBase64Byte, "utf-8");

重申一下,正确值应为ÈàHsX。我不明白是什么问题。任何帮助将不胜感激。

谢谢。

更新

让我进一步阐述这一点。

经典ASP中的RC4加密算法可以广泛使用,所以我不会浪费在这里发布的房地产。但是,我将展示base64 encoder/decoder我用于下面的经典ASP。

对于RC4,我使用的明文值是 foobar 。我正在使用的关键是测试。表面上看,解码base64字符串应该返回密码。解密密码应该返回明文值。

' Functions to provide encoding/decoding of strings with Base64.
' 
' Encoding: myEncodedString = base64_encode( inputString )
' Decoding: myDecodedString = base64_decode( encodedInputString )
'
' Programmed by Markus Hartsmar for ShameDesigns in 2002. 
' Email me at: mark@shamedesigns.com
' Visit our website at: http://www.shamedesigns.com/
'

    Dim Base64Chars
    Base64Chars =   "ABCDEFGHIJKLMNOPQRSTUVWXYZ" & _
            "abcdefghijklmnopqrstuvwxyz" & _
            "0123456789" & _
            "+/"


    ' Functions for encoding string to Base64
    Public Function base64_encode( byVal strIn )
        Dim c1, c2, c3, w1, w2, w3, w4, n, strOut
        For n = 1 To Len( strIn ) Step 3
            c1 = Asc( Mid( strIn, n, 1 ) )
            c2 = Asc( Mid( strIn, n + 1, 1 ) + Chr(0) )
            c3 = Asc( Mid( strIn, n + 2, 1 ) + Chr(0) )
            w1 = Int( c1 / 4 ) : w2 = ( c1 And 3 ) * 16 + Int( c2 / 16 )
            If Len( strIn ) >= n + 1 Then 
                w3 = ( c2 And 15 ) * 4 + Int( c3 / 64 ) 
            Else 
                w3 = -1
            End If
            If Len( strIn ) >= n + 2 Then 
                w4 = c3 And 63 
            Else 
                w4 = -1
            End If
            strOut = strOut + mimeencode( w1 ) + mimeencode( w2 ) + _
                      mimeencode( w3 ) + mimeencode( w4 )
        Next
        base64_encode = strOut
    End Function

    Private Function mimeencode( byVal intIn )
        If intIn >= 0 Then 
            mimeencode = Mid( Base64Chars, intIn + 1, 1 ) 
        Else 
            mimeencode = ""
        End If
    End Function    


    ' Function to decode string from Base64
    Public Function base64_decode( byVal strIn )
        Dim w1, w2, w3, w4, n, strOut
        For n = 1 To Len( strIn ) Step 4
            w1 = mimedecode( Mid( strIn, n, 1 ) )
            w2 = mimedecode( Mid( strIn, n + 1, 1 ) )
            w3 = mimedecode( Mid( strIn, n + 2, 1 ) )
            w4 = mimedecode( Mid( strIn, n + 3, 1 ) )
            If w2 >= 0 Then _
                strOut = strOut + _
                    Chr( ( ( w1 * 4 + Int( w2 / 16 ) ) And 255 ) )
            If w3 >= 0 Then _
                strOut = strOut + _
                    Chr( ( ( w2 * 16 + Int( w3 / 4 ) ) And 255 ) )
            If w4 >= 0 Then _
                strOut = strOut + _
                    Chr( ( ( w3 * 64 + w4 ) And 255 ) )
        Next
        base64_decode = strOut
    End Function

    Private Function mimedecode( byVal strIn )
        If Len( strIn ) = 0 Then 
            mimedecode = -1 : Exit Function
        Else
            mimedecode = InStr( Base64Chars, strIn ) - 1
        End If
    End Function

从ASP中,明文值可以通过密码正确实现:

  

plainText:foobar

     

cipherText:ÈàHsX

     

base64字符串:yOBIc4FY

     

解码的base64字符串:ÈàHsX

     

解密文字:foobar

但是,将密码作为base64字符串传递给JSP / Java,JSP / Java看起来像这样:

  

plainText:foobar(来自ASP)

     

cipherText:ÈàHsX(来自ASP)

     

base64字符串:yOBIc4FY

     

解码后的base64字符串:ÈàHs?X

     

解密文字:foobßr

所以,有些事情并没有在这里加起来。实际上,对于Java,对解密器的解密方式进行一处更改会返回foobar的正确解密文本。 Java代码中的RC4解密以int[]类型的形式获取密码。

public int[] decrypt(int[] ciphertext, byte[] key) throws Exception {
    return encrypt(ciphertext, key);
}

换句话说,我必须将密码从String类型转换为类型int[]。我使用下面的函数来做到这一点:

public static int[] convertToIntArray(byte[] input)
{
    int[] ret = new int[input.length];
    for (int i = 0; i < input.length; i++)
    {
        ret[i] = input[i] & 0xff; // Range 0 to 255
    }
    return ret;
}

我有两个选择。我可以将base64字符串解码为类型byte[]并解密,这将返回foobar

String base64String = "yOBIc4FY";

byte[] decodedBase64Byte = Base64.decodeBase64(base64String);

int[] cipheredText =  convertToIntArray(decodedBase64Byte);

或者,我可以将base64字符串解码为byte[]类型,然后将其转换为String类型,然后再将其转换为byte[]类型以反转为foobßr

String base64String = "yOBIc4FY";

byte[] decodedBase64Byte = Base64.decodeBase64(base64String);

// ÈàHs?X
String decodedBase64String = new String(decodedBase64Byte, "ISO-8859-1");

int[] cipheredText =  convertToIntArray(decodedBase64String.getBytes());

我的猜测是原始字节序列是正确的,因为RC4解密函数成功返回foobar。但是,当我将字节序列转换为某个字符编码集的字符串时,它会更改该值,最终使用解密值foobßr

为什么ASP和JSP / Java报告稍微不同的密码值仍然没有意义? ASP将base64字符串或密码解码回明文值没有问题。我不知道问题是ASP,JSP还是两者兼而有之。

1 个答案:

答案 0 :(得分:2)

at Object.$watchCollectionAction [as fn] <div class="masonry-brick ng-scope" ng-switch="" on="{{graphic.length}}" 的正确解码是6个字节,具体为:

yOBIc4FY

c8 e0 48 73 81 58 值可能只是将字符ÈàHsX忽略为不可打印。

证明:

0x81

要解决您的后续问题 - 您应该使用从base64解码器获得的字节数组。如果需要,可将其转换为y O B I c 4 F Y 110010 001110 000001 001000 011100 111000 000101 011000 11001000 11100000 01001000 01110011 10000001 01011000 c8 e0 48 73 81 58 ,但不要创建int[],因为编码会搞砸它:

String

您可以在此处看到原始正确字节static void printByteArray(byte[] bytes) { for (byte b : bytes) { System.out.print(Integer.toHexString(b & 0xff) + ", "); } System.out.println(); } public static void main(String[] args) { byte[] cipherBytes = Base64.getDecoder().decode("yOBIc4FY"); printByteArray(cipherBytes); // c8, e0, 48, 73, 81, 58 - correct cipherBytes = new String(cipherBytes).getBytes(); printByteArray(cipherBytes); // c8, e0, 48, 73, 3f, 58 - wrong // your results may vary depending on your default charset, // these are for windows-1250 } 已更改为问号0x81(字节?),因为0x3f不代表有效字符在从字节数组创建0x81时使用的字符集中。