簡體   English   中英

無法在Android中解析為整數

[英]Unable to parse as integer in Android

我想對某些String值實現encryptdecrypt操作。 我已經正確加密,但是我不知道如何decrypt該值,例如:

jsonString Values ={"Response":"NJGOkF2EvOIpfKG14LHQZrVfj\\/OEJvopi+OKU+q5G2ynDbVUnIckfMLGCCsxcY9+BmVg+KJXF1ls\\nGf2rWg73iyowyq6THyDfBS8uZnSp9PfS3bJCFb6YWX4\\/\\/uxjDwtZ","statusFlag":"true"}

當我解密時,我得到了NumberFormatException

這是我簡單的加密類

import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;


    public class SimpleCrypto {

            public static String encrypt(String seed, String cleartext) throws Exception {
                    byte[] rawKey = getRawKey(seed.getBytes());
                    byte[] result = encrypt(rawKey, cleartext.getBytes());
                    return toHex(result);
            }

            public static String decrypt(String seed, String encrypted) throws Exception {
                    byte[] rawKey = getRawKey(seed.getBytes());
                    byte[] enc = toByte(encrypted);
                    byte[] result = decrypt(rawKey, enc);
                    return new String(result);
            }

            private static byte[] getRawKey(byte[] seed) throws Exception {
                    KeyGenerator kgen = KeyGenerator.getInstance("AES");
                    SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
                    sr.setSeed(seed);
                kgen.init(128, sr); // 192 and 256 bits may not be available
                SecretKey skey = kgen.generateKey();
                byte[] raw = skey.getEncoded();
                return raw;
            }


            private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
                SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
                    Cipher cipher = Cipher.getInstance("AES");
                cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
                byte[] encrypted = cipher.doFinal(clear);
                    return encrypted;
            }

            private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
                SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
                    Cipher cipher = Cipher.getInstance("AES");
                cipher.init(Cipher.DECRYPT_MODE, skeySpec);
                byte[] decrypted = cipher.doFinal(encrypted);
                    return decrypted;
            }

            public static String toHex(String txt) {
                    return toHex(txt.getBytes());
            }
            public static String fromHex(String hex) {
                    return new String(toByte(hex));
            }

            public static byte[] toByte(String hexString) {
                    int len = hexString.length()/2;
                    byte[] result = new byte[len];
                    for (int i = 0; i < len; i++)
                            result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue(); //2 * i, 2 * i + 2
                    return result;
            }

            public static String toHex(byte[] buf) {
                    if (buf == null)
                            return "";
                    StringBuffer result = new StringBuffer(2*buf.length);
                    for (int i = 0; i < buf.length; i++) {
                            appendHex(result, buf[i]);
                    }
                    return result.toString();
            }
            private final static String HEX = "0123456789ABCDEF";
            private static void appendHex(StringBuffer sb, byte b) {
                    sb.append(HEX.charAt((b>>4)&0x0f)).append(HEX.charAt(b&0x0f));
            }

    }

這是日志貓信息。

01-03 11:30:51.154: W/System.err(437): java.lang.NumberFormatException: unable to parse '{"' as integer
01-03 11:30:51.164: W/System.err(437):  at java.lang.Integer.parse(Integer.java:383)
01-03 11:30:51.164: W/System.err(437):  at java.lang.Integer.parseInt(Integer.java:372)
01-03 11:30:51.164: W/System.err(437):  at java.lang.Integer.valueOf(Integer.java:528)
01-03 11:30:51.164: W/System.err(437):  at com.json_to_server.SimpleCrypto.toByte(SimpleCrypto.java:63)
01-03 11:30:51.164: W/System.err(437):  at com.json_to_server.SimpleCrypto.decrypt(SimpleCrypto.java:20)
01-03 11:30:51.164: W/System.err(437):  at com.json_to_server.EncryptDecrypt_Demo.POST(EncryptDecrypt_Demo.java:202)
01-03 11:30:51.174: W/System.err(437):  at com.json_to_server.EncryptDecrypt_Demo$HttpAsyncTask.doInBackground(EncryptDecrypt_Demo.java:267)
01-03 11:30:51.174: W/System.err(437):  at com.json_to_server.EncryptDecrypt_Demo$HttpAsyncTask.doInBackground(EncryptDecrypt_Demo.java:1)
01-03 11:30:51.174: W/System.err(437):  at android.os.AsyncTask$2.call(AsyncTask.java:185)
01-03 11:30:51.174: W/System.err(437):  at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
01-03 11:30:51.174: W/System.err(437):  at java.util.concurrent.FutureTask.run(FutureTask.java:138)
01-03 11:30:51.174: W/System.err(437):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
01-03 11:30:51.174: W/System.err(437):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
01-03 11:30:51.174: W/System.err(437):  at java.lang.Thread.run(Thread.java:1019)

我想解密此值。 我不知道我必須在哪里更改SimpleCrypto class的代碼

jsonString Values = {"Response":"NJGOkF2EvOIpfKG14LHQZrVfj\/OEJvopi+OKU+q5G2ynDbVUnIckfMLGCCsxcY9+BmVg+KJXF1ls\nGf2rWg73iyowyq6THyDfBS8uZnSp9PfS3bJCFb6YWX4\/\/uxjDwtZ","statusFlag":"true"}

我假設您正在decrypting整個JSON字符串,並且我認為您只需要decrypt

該字符串: NJGOkF2EvOIpfKG14LHQZrVfj\\/OEJvopi+OKU+q5G2ynDbVUnIckfMLGCCsxcY9+BmVg+KJXF1ls\\nGf2rWg73iyowyq6THyDfBS8uZnSp9PfS3bJCFb6YWX4\\/\\/uxjDwtZ

因此,您應該parse JSON並從JSON獲取Response string ,然后將其decrypt

更新:您可以像這樣解析json字符串:

String value = "YOUR_JSON_STRING";
    try {
        JSONObject mJsonObject = new JSONObject(value);
        String response = mJsonObject.getString("Response");
        //Decrypt response string 

    } catch (JSONException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

現在,您在response variable有了encrypted string 現在您可以decrypt response string

我已經測試過您的課程,並且可以正常運行。 這是我的測試:

public static void main(String[] args) throws Exception {
   String message = "Some string that i want to encrypt and decrypt";
   String key = "123";

   String encrypted = SimpleCrypto.encrypt(key, message);
   p(encrypted);

   String decrypted = SimpleCrypto.decrypt(key, encrypted);
   p(decrypted);
}

private static void p(String message) {
   System.out.println(message);
} 

並輸出:

B7498FF642FA8B81289AE8E59E19F081A27B766BE3290617CC15F857BF055DA2668BF81181E26AE2F790968DF39CC070
Some string that i want to encrypt and decrypt

之所以得到NumberFormatException,是因為您的類僅解密十六進制的字符串,但是此十六進制不解密。

您嘗試解析為十六進制數字的整數字符串“ NJ”。 但是十六進制只有0-9和AF符號。 將您的收入字符串更改為僅十六進制符號。

我認為result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue(); 給您錯誤,因為您的十六進制字符串可能包含字符文字,因此Integer.valueOf()函數為您提供NumberFormatException

對於十六進制字符串到字節數組的轉換,請檢查[鏈接] https://stackoverflow.com/a/140861/3131537

希望能解決您的問題

您正在嘗試解析不僅包含數字而且包含文本(字符串)的整個字符串。 請檢查您的代碼,然后提出一個問題

您的解決方案有效,您對所獲取數據的解釋與實際發生的情況不一致。

您的JSON響應不是加密的字節數組,而是編碼的String 為了通過網絡跨字節數組(或相應的位或任何二進制數據)進行流傳輸,通常不會以原始格式發送它。 相反,您想將原始數據編碼character

由於您的JSON響應看起來像字符流和字節不是原始格式,第一個假設,我可以做的是它的使用中最常見的二進制字符串編碼之一的編碼數據- Base64編碼

下面的字符串(響應)是有效的Base64編碼的字符串,而您的解密方法要求使用十六進制編碼的字符流。

NJGOkF2EvOIpfKG14LHQZrVfj / OEJvopi + OKU + q5G2ynDbVUnIckfMLGCCsxcY9 + BmVg + KJXF1ls \\ nGf2rWg73iyowyq6THyDfBS8uZnSp9PfS3bJCFb6YWX4 // uxjDwtZ

提取正確的響應:

由於JSON“允許”您轉義正斜杠和其他轉義序列,因此您的Base64響應需要略微格式化。

我刪除了前斜杠的轉義符,並換行了(\\ n)的'\\'轉義符。 結果字符串看起來像(注意\\ n):

NJGOkF2EvOIpfKG14LHQZrVfj/OEJvopi+OKU+q5G2ynDbVUnIckfMLGCCsxcY9+BmVg+KJXF1ls\\nGf2rWg73iyowyq6THyDfBS8uZnSp9PfS3bJCFb6YWX4//uxjDwtZ

這是有效的Base64字符串,您可以在此處進行測試(通過按回車鍵並將\\ n其余文本帶到新行中,用換行符替換\\ n)。

在此處輸入圖片說明

請注意,結果是下載了一個二進制文件-證明解碼后的值實際上是有效的二進制原始數據。

修改代碼:

NumberFormatException可以明顯看出,您的decrypt方法期望使用十六進制編碼的字符流,但它不會得到。

根據您的代碼,加密函數將返回字符串的十六進制編碼值。 這也是有效的,因為十六進制還以可讀形式表示二進制值。 但是,您可能需要在集成中進行級別設置以與編碼方案保持一致。

回到您的算法上,您的解密方法期望使用十六進制格式的加密數據,但是您得到的是Base64編碼的String。

符合您的邏輯期望(我不想更改您的原始基本代碼)

  1. 我們將不得不對Base64編碼的String進行解碼 -可以使用各種樣式,我為此測試使用了org.apache.commons.codec.binary.Base64
  2. 將其轉換為十六進制
  3. 將其提供給解密方法

在代碼中這樣翻譯的步驟序列(在我的測試類main方法中):

String encoded = "NJGOkF2EvOIpfKG14LHQZrVfj/OEJvopi+OKU+q5G2ynDbVUnIckfMLGCCsxcY9+BmVg+KJXF1ls\\nGf2rWg73iyowyq6THyDfBS8uZnSp9PfS3bJCFb6YWX4//uxjDwtZ";

String key = "abc";

String decoded = toHex(Base64.decodeBase64(encoded));
System.out.println(decoded);

String decrypted = decrypt(key, decoded);
System.out.println(decrypted);

關於您的加密方案:

您的AES加密方案使用默認的AES方案( Cipher.getInstance("AES"); ),它轉換為Cipher.getInstance("AES/ECB/PKCS5Padding"); 在SunJCE實施中。

當我使用隨機密鑰abc運行它時

javax.crypto.BadPaddingException: Given final block not properly padded

當然,這是密鑰錯誤情況,因為我沒有用於加密/解密數據的密鑰。

您可以使用正確的密鑰和上述更改來測試此方案, 它應與當前的加密方案一起使用。

我的測試用例:

作為一個測試用例,我禁止解密的方法是,將解密方法中的Cipher.getInstance("AES")替換為

Cipher.getInstance("AES/ECB/NoPadding");

我得到了一個無例外的字符集合,它們無一例外都是垃圾值,這是可以理解的-原因,我再次使用了一個與您要使用的鍵不匹配的隨機鍵。

;l:z«1†ŠåÎàÏÙQPÞ—?ñGv’€ò;PöøïÇE1:‰§ŒÔ³

您正在使用JSON數據作為字符串數據。 您只需要選擇JSON的“ response”部分值,就像這樣

JSONObject jO= new JSONObject(value);
String response = jO.getString("Response");

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM