2016-02-28 4 views
0

Я искал весь день (около 12 часов), как справиться с этим и не мог найти что-нибудь для работы для меня, поэтому я решил задать еще один вопрос по этой теме.RSA от Android до PHP

Моя установка:

  1. Принимая верительные грамоты от пользователя
  2. шифровать их с помощью открытого ключа RSA, а затем 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); 

Это мой открытый ключ без START и END:

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

Моя проблема заключается в том, что если я зашифровать его с помощью Android, а затем Base64.encode его, Я получаю другую строку, чем если бы я шифровал PHP с помощью того же открытого ключа

Я пробовал шифровать работа "админ" с обеих сторон, и вот что у меня получилось: Струнный получил от Android:

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

Строка из PHP:

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); 
    } 

Почему не т wo генерируют одну и ту же строку при шифровании и base64? Я подозреваю некоторые проблемы с кодировкой, но я не могу понять их. Пробовал форсировать UTF-8 на обоих, но результат тот же. Любые идеи?

Спасибо!

EDIT:

Используя эту base64 библиотеку для Java: https://sourceforge.net/projects/iharder/files/base64/2.3/

по умолчанию один из Android дает те же результаты, так что, да ..:/

EDIT 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. Я редактировал свой вопрос (EDIT 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

I второй OAEP. Поскольку обманщик использует phpseclib, не стесняйтесь также рекомендовать MGF1 + SHA256. ;) –