繁体   English   中英

字节数组在替换字符串变量时给出不同的输出

[英]Byte array giving different output on replacing string variable

我正在尝试替换一些涉及字符串变量存储的现有逻辑,以使用字节数组(出于安全原因)。 下面有两个块方法 A() 与旧逻辑和方法 B() 与替换。 但是,在类似点打印输出时,我看到字节数组的输出不同。 我错过了什么吗?

public class HelloWorld{

     public static void main(String []args){
        System.out.println("Hello World ");
        A();
        B();
     }

     public static void A()
     {
         String expDetails = "";

         if (true) {
            String expYear = "1986";
            expDetails = expYear;
        }
        System.out.println("Output in between "+expDetails);
        // expiry month in MM
        String monthStr = "";
        if (true) {
            String expiryMonth = "12";
            int month = Integer.parseInt(expiryMonth) + 1;
            expDetails += month > 9 ? String.valueOf(month) : "0" + month;
        }

        System.out.println("Output "+expDetails);
     }

     public static void B()
     {
         byte[] expDetailsNew = null;
         if (true) {
            String expYear = "1986";
            expDetailsNew = expYear.getBytes();
            System.out.println("Inside");
        }
        System.out.println("Output in between "+expDetailsNew.toString());
        String monthStr = "";
        if (true) {
            String expiryMonth = "12";
            int month = Integer.parseInt(expiryMonth) + 1;

            if(month>9)
            {
                byte[] c = new byte[expDetailsNew.length + Integer.toString(month).length()];
                System.arraycopy(expDetailsNew, 0, c, 0, expDetailsNew.length);
                System.arraycopy(expDetailsNew, 0, c, expDetailsNew.length, Integer.toString(month).length());

                String finalVal = new String(c);

            System.out.println("Output "+finalVal);
            }

        }

     }

}

以下是输出 -

Hello World 
Output in between 1986
Output 198613
Inside
Output in between [B@6d06d69c
Output 198619

更新

根据@VGR 的回答,尝试像这样附加月份值 -

CharBuffer another = CharBuffer.allocate(2); 
new Formatter(another).format("%02d", month); 
expDetailsNew.append(another);
expDetailsNew.flip();
System.out.println("Output "+expDetailsNew.toString());

但是输出然后是空的。

为避免在字符串中存储敏感信息,请使用char数组。 不要使用平台的默认字符集转换为字节; 你冒着破坏信息的风险。 事实上,Java SE 中许多与安全相关的方法已经使用了char数组:

虽然您可以使用System.arraycopy ,但CharBuffer更容易使用,它甚至有一个有用的toString方法。

您的原始问题显示的代码比此问题中的代码清晰得多,因此我将使用其中的代码:

CharBuffer expDetails = CharBuffer.allocate(6);

// extract expiry year in YYYY
if (!CommonUtil.isEmpty(paymentDetails.getExpiryYear())) {
    expDetails.append(paymentDetails.getExpiryYear());
}

// expiry month in MM
if (!CommonUtil.isEmpty(paymentDetails.getExpiryMonth())) {
    int month = Integer.parseInt(paymentDetails.getExpiryMonth()) + 1;
    new Formatter(expDetails).format("%02d", month);
}

expDetails.flip();

reqParams.put("CardNum",
        encrypt(params[4], paymentDetails.getCardNumber()));
reqParams.put("expiryDate", encrypt(params[4], expDetails.toString()));
reqParams.put("CVVNum",
        encrypt(params[4], paymentDetails.getCvvNumber()));

正如漏洞报告所指出的,String 对象是不可变的并且可以被内部化,以减少冗余分配。 这意味着恶意代码理论上可以访问其他对象使用的 String 对象。 为了避免这种可能性并加强对字符串值的安全性,您可以更改您的encrypt方法以接受char[]参数而不是字符串。 例如:

public byte[] encrypt(String key, char[] sourceValue) {
    Formatter hex = new Formatter(Locale.US);
    for (char c : sourceValue) {
        hex.format("%04x", (int) c);
    }
    return hex.getBytes(StandardCharsets.UTF_8);
}

(这只是一个例子,基于您的评论;我不知道您的encrypt方法实际上是做什么的。)

另外,永远不要写一个空的catch块。 由于这似乎是一个 Web 服务方法,您应该能够删除 try/catch 并简单地将必要的异常添加到您的方法的throws子句中。 您真的不希望用户认为应用程序在实际运行时正在运行,对吗?

System.out.println("Output in between "+new String(expDetailsNew));
以上解析对象引用。

尝试改变

System.arraycopy(expDetailsNew, 0, c, expDetailsNew.length, 

System.arraycopy(Integer.toString(month).getBytes(), 0, c, expDetailsNew.length, 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM