2011-10-25 1 views
1

私はAndroidアプリケーションの暗号化/復号化アルゴリズムを実装するのに数週間かかっています。私は自分のウェブサイトからダウンロードされ、Androidデバイスの外部ストレージに保存されているライセンスキーを実装しています。アプリケーションはファイルの内容を読み取り、サーバーの公開鍵を使用してそれを復号化します(はい、私はクライアントの秘密鍵ですべきですが、私の目的は大丈夫です)。問題は、最後の文字列の中に疑問符を含む黒い四角がたくさんあることです。私はstackoverflow上の他の多くの記事を読んだことがあるが、私は "唯一の"問題は、文字列に10文字が必要な場合でも、文字列が長い255バイト(2048ビットのRSAキー)残りの文字は黒で塗りつぶされます。なぜnewPlainText varが "Hello World!"のように長くないのですか? ?ここで私のコードの下に...多くの事前に感謝!Java Android - 復号化されたバイト配列 "Hello World!"の代わりに255バイト長さ

public boolean licenseValid() throws IOException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException{ 
    java.io.File file = new java.io.File(Environment.getExternalStorageDirectory().toString() , 
      "/folder/file.lic"); 
    byte[] fileBArray = new byte[(int)file.length()]; 
    FileInputStream fis = new FileInputStream(file); 

    // Read in the bytes 
    int offset = 0; 
    int numRead = 0; 
    while (offset < fileBArray.length 
      && (numRead=fis.read(fileBArray, offset, fileBArray.length-offset)) >= 0) { 
     offset += numRead; 
    } 

    // Ensure all the bytes have been read in 
    if (offset < fileBArray.length) { 
     throw new IOException("Could not completely read file "+file.getName()); 
    } 

    fis.close(); 

    // Decrypt the ciphertext using the public key 
PublicKey pubKey = readKeyFromFile(); 
Cipher cipher = Cipher.getInstance("RSA"); 
cipher.init(Cipher.DECRYPT_MODE, pubKey); 
byte[] newPlainText = cipher.doFinal(fileBArray); 

    // THE FOLLOWING TOAST PRINTS MANY <?> AND THAN THE DECRYPTED MESSAGE. THE TOTAL NUMBER OF CHARACTERS IS 255, EVEN IF I CHANGE ENCRYPTED TEXT! 
toast(String.valueOf(cipher.doFinal(fileBArray).length)); 

    if (new String(newPlainText, "utf-8").compareTo("Hello World!") == 0) 
     return true; 
    else 
     return false; 
} 

PublicKey readKeyFromFile() throws IOException { 
    Resources myResources = getResources(); 
    //public key filename "pub.lic" 
    InputStream is = myResources.openRawResource(R.raw.pub); 
ObjectInputStream oin = 
    new ObjectInputStream(new BufferedInputStream(is)); 

try { 
     BigInteger m = (BigInteger) oin.readObject(); 
     BigInteger e = (BigInteger) oin.readObject(); 
     RSAPublicKeySpec keySpec = new RSAPublicKeySpec(m, e); 
    KeyFactory fact = KeyFactory.getInstance("RSA"); 
    PublicKey pubKey = fact.generatePublic(keySpec); 
    return pubKey; 
    } catch (Exception e) { 
    throw new RuntimeException("Spurious serialisation error", e); 
    } finally { 
    oin.close(); 
    } 
} 

答えて

2

RSAで暗号化すると、入力と出力は常にキーと同じ長さになります。あなたの場合、それは256バイト(= 2048ビット)でなければならないので、まずあなたのコードをチェックしてください。バイトがありません。 入力が短くなると、パディングを適用する必要があり、サーバーとクライアントが別のものを使用しているように見えます。 Cipher.getInstance("RSA")はプラットフォームのデフォルトを使用しますが、これはおそらくAndroidとJava SEでは異なります。両方のプログラムで明示的にパディングを指定する必要があります。

Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding");

ところで、あなたが本当にあなたのアプリとプライベート鍵を配布するので、公開鍵を使用して行うには正しいことではありません。このような何か。 (ただし、暗号化方式全体が安全かどうかは別の問題です)。

+0

としよう:スレッドで 例外「メイン」java.security.NoSuchAlgorithmException:RSA /なし/ PKCS1Paddingをサポートしているすべてのプロバイダを見つけることができませんそれは私に次のエラーを与える 「RSA /なし/ PKCS1Padding」。おそらくあなたが想定していることが本当の問題かもしれません...私は今何を試すことができますか? – Vale

+0

これはAndroidかあなたのサーバーにありますか? 'Cipher.getInstance(" RSA/NONE/PKCS1Padding "、" BC ");' –

+0

こんにちは、pub.key、priv.keyとファイルを作成します。私のラップトップでは、私はpub.keyをアンドロイドプロジェクトのres-> rawフォルダに入れ、file.licはAndroidデバイスの外部メモリのフォルダに入れます。私は、AndroidがBouncyCastleを埋め込んでいないことをウェブ上で読んだ。私はそれがパディングの問題だと思う...私は何を試すことができますか? – Vale

関連する問題