Массив байтов, дающий различный вывод при замене строковой переменной - PullRequest
0 голосов
/ 10 июля 2019

Я пытаюсь заменить существующую логику, связанную с хранением в строковой переменной, на использование байтового массива (по соображениям безопасности). Ниже приведены два блока метода 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());

Но тогда вывод пуст.

Ответы [ 2 ]

1 голос
/ 11 июля 2019

Чтобы избежать хранения конфиденциальной информации в строках, используйте 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 блок.Поскольку это, по-видимому, метод веб-службы, вы можете просто удалить try / catch и просто добавить необходимые исключения в предложение throws вашего метода.Вы действительно не хотите, чтобы пользователи думали, что приложение работает, когда оно на самом деле не работает, верно?

0 голосов
/ 10 июля 2019

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, 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...