2016-02-28 181 views
0

我一直在尋找整天(aprox。12小時)如何處理這個,並找不到任何東西爲我工作,所以我決定就這個話題提出另一個問題。RSA從Android到PHP

我的設置:使用RSA公鑰

  1. 從用戶以憑證
  2. 對其進行加密,然後BASE64
  3. 發送到服務器
  4. BASE64_DECODE,解密和檢查憑證

這是我在Android上用於加密的代碼:

public class Encrypter { 
     public static PublicKey loadPublicKey(Context context) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { 
      InputStream is = context.getAssets().open("public_key.txt"); 
      byte[] bytes = new byte[is.available()]; 
      is.read(bytes); 

      PublicKey publicKey = KeyFactory.getInstance(RSA).generatePublic(
        new X509EncodedKeySpec(Base64.decode(bytes))); 

     return publicKey; 
    } 

    private static byte[] enc(String text, PublicKey pubRSA) throws Exception { 
     Cipher cipher = Cipher.getInstance(RSA); 
     cipher.init(Cipher.ENCRYPT_MODE, pubRSA); 
     return cipher.doFinal(text.getBytes("UTF-8")); 
    } 

    public final static String encrypt(String text, PublicKey uk) { 
     try { 
      return Base64.encodeBytes(enc(text, uk)); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 
} 

我如何使用它:

String username = "admin"; 
    PublicKey pubk = Encrypter.getPublicKey(this); 
    username = Encrypter.encrypt(username, pubk); 

這是我沒有STARTEND公鑰:

MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsfPDQ7tRqUw8oTPcNG3GR9OyhWnrtQXj2gmzTKdLncPIuolG1GTjYyZO25+cHSgHBlFmc20cKO0uasveZWCwuBTmMY3kVYtVblxUbHmHakLc2CRsKlCA3GAU/OAvfQfzcRUE0O1R138XcTydDGNgWKthqePJz97sEtg8nY55imVUTfRJPOeMvn1/vQQY50OTGniyoI+sh66P/0xpjrZQdIKaNADD5tQbDmrrJjoocC/GuwqBizi7rmU/p/9udNj5hCKqxL6PmejDsHss+UrhBx5t1/iem2yEBhvuOPDyvBPn/ZqAEKeAUKyf+Z5d3XQAlzJq5UjliRM2IA/K6uUBCQIDAQAB 

我的問題是,如果我對其進行加密使用的是Android,然後Base64.encode它,我得到一個不同的字符串比如果我使用相同的公鑰加密從PHP加密

我試着加密關於雙方在這裏都工作 「管理」 是我得到的: 字符串於Android的了:從PHP

hF8ykDKLYVJOnHE5Uswq0+BasIRqTLnFIjvy2rLxfe/oDJ0GbhjTjoizNuSk2grKbAgkJqFN5uAFuhkqqjyxoSJlJNsQi5QRis9FDUIm1iAhjSD8olTBFky+q1pqYQsQ/Cj+9qSVTnoKpB2oJyeEk2Zx7mYegHKT/yItDtsSLa7fURaxygp1osj0Nz8pas21zXgMIyG2wKARG9IlxdBo4Vl2nj7iKwPCkHMrSeXzFjDsKOkwBzMoPuUUGSFUZ0QbL+b/Ha+Rgdb7oItzTvBfHsoL9m91j20NhqapKRYkJ2pPUhPPVDZtTzO/JPKK4ndzg32w7jKqb9zinOBcilQdGg== 

字符串:

oh8fNeY8FwPqUkvJhFQr/2IPgdj7XEUNHjc7+KZwRGot+4DIQWtxv3N4UtzbpvkwcgI/kUjXZOz+mNSzvTEVpmZprOWBow/zlbCO7tLgH2Q131gATZdGxPEgOIVbTOWQkXL+d8x+jODnPhaXb8vUB2boQmd70ifBAq2C5mMCGPeA/gRwNquwdEG62W4zvaeXzXc6sXCXXvE6cgaWLOhZWFnLyo2ulFrkGk9XXOaWoS3HYnS35n8xHxulSEeAJOmGgEd56cSbDIlJrD9H5k6mb6PX0/eLoC7J9vdBhdM8nJVviL6NxtiOtDTCWVFb4k9il8Sksz8eascFM8yAB0KvRw== 

對於加密在PHP中我使用phpseclib Laravel 5.2框架下

方法來檢查憑證

public function creds_valid(Request $request) { 
     $inputs = $request->all(); 

     $username = $inputs['username']; 
     $password = $inputs['password']; 

     $private_key = file_get_contents(storage_path() . "/phpseclib/public_key.txt"); 
     $rsa = new RSA(); 
     $rsa->loadKey($private_key); 

     $username = $rsa->decrypt(base64_decode($username)); 
     $password = $rsa->decrypt(base64_decode($password)); 

     $credentials = [ 
      'username' => $username, 
      'password' => $password, 
//   'active' => 1 
     ]; 

     return Auth::guard()->attempt($credentials); 
    } 

爲什麼不是第t wo算法在加密和base64上輸出相同的字符串?我懷疑一些編碼問題,但我無法弄清楚。試圖強制兩個UTF-8,但結果是一樣的。任何想法?

謝謝!

編輯:

使用的Java本的base64庫: https://sourceforge.net/projects/iharder/files/base64/2.3/

默認一個從Android爲使相同的結果,是啊..:/

編輯2: 首評建議檢查是否有任何一方更改併發執行的輸出和奇怪,是的.. PHP的一個..爲什麼?

這是從php artisan tinker

base64_encode($rsa->encrypt('admin')) 
=> "T3dBTadyEjvSM96lCwELNzXHNh5bEJtW6QvgdrVT0wZ2KFq8Cs+s7/+IjSrISlNC+ygF+XPhYjEUHa+FSqzgT68KftcVQYL84w8Thbiy6ElLqs7WAbLAaKk10kBqEPNtI0jItOJFXGA07SsQu6g5+OUWfEFShBPg8uSxSYPsjhvATpw6lLCRtVQYqAL1MUwwmaho/ktih5UJgpiCYdwpa0ROiPboKloO0CFOAkR+5rybSLH73p3Fxf1y46qgA3BoPenillkMW8kgv1/bFj1rpRVi2Ca3ioMQt0fOPGchoe3ikz5I6IrrAK0aYhwj3kpoQ2+doLUV+EKXs8iFkA+cjQ==" 
>>> base64_encode($rsa->encrypt('admin')) 
=> "XJZrhFpw1UsBEC2yKMv0PVQ/H0vvBSXEZEsjQ4vlvjgktifCGAPsac3zwarlV2+TOoNKhn7nCqWer2Gz60UyoHS0xYyNvt/i3Ogsn2ccxhpKRtrB2CEMJOzSdLoUe+4JEObdU1b6SR4ysFbFEjFvo+zWUAfT7i2vM9bdZkwcrL6S2a4bBeWk3t2l91URatggzTOBFtxUB4zHTKyo1SSuR6uqm2q/Jbakj07e64ZZQmWiKY4inDZNgaVVLE+wNq++J4aLwRhSZG4wXuPgNeGHfwgZ3bytlRJUrrNXMXExa1C8eu/js3+WiYFSXPIiTeuQaxsih+suj0abDTFjJygNMA==" 
>>> base64_encode($rsa->encrypt('admin')) 
=> "DVAFTjZ1Ah6mpN699/PitPj0nLNLhz4zGux9uYLQHmANR/CYEt63+z0vE2xQI9oKE/V4K5a335wvJpz+70hMy6G30cKAwerZ8PudbZgnpGRaF0YlRwzZEQ+XqV5qdQXE6kb4plVZrYrpyHAiPTmO54V+UvCp2YPbNY3Qcr+vbIrn0CZJ7lMwgE9NCGWwiIJF6G6/z4zqc+UbBG9+WUtf16BU8CXhbeU4FOSeuxYr9xbGbjAvtUZXrXpaQPYwgCuWURTWcN2fxmm5fAZuU74rPVMW5slTxTVafcIcUI0bFuMdsx3xj9VIImYhmbM0DTXT/gm66nxSy7aAvj5ckmemfA==" 
>>> base64_encode($rsa->encrypt('admin')) 
=> "Po8lzluh+ChWdHBxvThrn06kZ1cugTvEvV6UU8JroeM2aYwX4XH9hMSt1U+XmKkmdgxLRXwKUMsYcT7rF7I92tLW6T6fjTED1HoXXWS35okc1zhPTvXFqvMdXq7r4meLrcPmJjfsJsKnso4Ws2aIzHjQxfbPAHQNE2FD1bbOA0aD21MU8HR1qckTFosOP3O8KpxBQW3Z0aTX+k0sy0edwHfHCjQxQ9ne3oWcY+JiKCSFbyWoYxGQML0N11jA5Jik4K3jMA7cDQQzUutWUGN/ABv7OoXYKbfv/3IA8Uqu6jxSgBZjsLb4iUdFtw9QlwOsr4w2flCsPtye0vnDsjOduQ==" 
>>> base64_encode($rsa->encrypt('admin')) 
=> "rnkB57WUXMw87Hxc6e6MGraGryEQ+3HVwbGEexIGrs4jlqzBHZig7/ykfHzGgZGlrtYGY/FB3Mn6kfkwH1SXVAV6QPdnp0ktxbrqHJmQDDrLxsBlQGbZnSSVglV2EHn9Vm++iiygspv+IRMmOB6XOBxWMcV2AeAGa86EwTj3AKdcOeSPzrIB04G2mH695rEwLHC69KeBZ5vCuPAvVZ5AjhzsutcNEK5WLIcxcFbi1PQb7Amp3mPMpW3g0w+LkU6RkW8GGZ5gPu15PfvT/r8CCDaJbTwCLN2XPAa1R+/x0IZgSM2Tv/qOJBGdkkjGM8/lXeTGW8/oKU85bdlVqEBxdA==" 
>>> base64_encode($rsa->encrypt('admin')) 
=> "cX+CkQR+t9fdWMo2jHs7FdbmFzcAYkLfhNo6J0O3rAMtg8iR/KoN+RfNA6WQN4DIWMiGsN1F/ipAxiOo8K0V7x7EODgpbw2zGQBL/ueWJyD00UIA0WsXo93ubIXOJ+62dFbz7Ioc9Gtwv3q7HhtmKIh2oDxpffU1uOWzBGE8MW5cYvuWGHRqsgcKxFfiOJht+GkZUS2gdUe7/ke5YsEGLJs4PJzuk/NnPvsKEdlNHoAT+Vyzc3yW9+FtL8OpXDplACFaRS/Urulmvkd5wiy7dhCh9L1QDdgUZshkQ0In2254LFME5tVkpES0ZlD8eLZih84sioTIyeGoUj1gdkHxdw==" 
>>> base64_encode($rsa->encrypt('admin')) 
=> "JFVZ2dhi6vsLeiXwPDxisxRa+56fCHIM9RORhJ51hgdAr7qeb7O2o0Xx3AVJB/CfX6ZXOFwZ38sATGDpHgEbYT5Tui12IMMLTgLnQnnxyxX8+A5AfYCpAzHOr9Xr41fHdtVDTexcI+77yEakhh57SGhfUQhoTll/k73CDymLkF/DkKw21EY9DXgscffKB5giyC3bd4CiqCZ3j/aa0T70NKtjDT3H5zqrHd3dhqblYRVE7rAbKHYPz6hrv5TUX2rX45er4o53cihGOuzTlwOGDa5f0HGlepnXSvGlgmqCRMbina4LepAlker93HVD56I7rtiRRLqz9BUahkt3GSoZfA==" 
>>> 
+0

做任何兩個密文的改變,如果你再次執行加密(在原始明文上)? –

+0

@ ArtjomB。我編輯了我的問題(編輯2) – csanonymus

回答

2

當加密是隨機的,它提供了semantic security的輸出。該屬性不允許被動的密文觀察者確定觀察到的密文背後的明文是否在之前被髮送。這是通過隨機填充(PKCS#1 v1.5填充類型2或OAEP)實現的。

如果你想確定你的代碼是否兼容,你需要在一面進行加密並在另一面進行解密。

看起來您的代碼應該按原樣工作,具體取決於默認值。您應該始終指定您自己的配置,以防止在切換系統時默認設置不兼容。

在Java中,你應該總是提供一個完全合格的密碼字符串:

  • Cipher.getInstance("RSA/ECB/PKCS1Padding");
  • Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");(OAEP是時下優先)
  • Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");(OAEP是時下優先)

在phpseclib中,您應該始終更改默認值:

  • $rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
  • 爲OAEP與SHA-1:

    $rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_OAEP); 
    $rsa->setHash("sha1"); 
    $rsa->setMGFHash("sha1"); 
    
  • 爲OAEP與SHA-256:

    $rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_OAEP); 
    $rsa->setHash("sha256"); 
    $rsa->setMGFHash("sha1"); 
    
+0

我第二個OAEP。由於提問者使用phpseclib,所以隨時推薦MGF1 + SHA256。 ;) –