4

Я пытаюсь зашифровать данные в андроида стороне и расшифровать его в сторону PHP я использую phpseclib в PHP для создания общественных/частных ключейОткрытый/закрытый ключ шифрования Android-PHP

после того как я генерировать ключи этого открытый ключ я получил в PHP стороны:

-----BEGIN RSA PUBLIC KEY-----". 
      "MIGJAoGBAKks62Itns2uU/dVZJ4kCkMinHgyeh/rdMD53a4Zu2a76OIJvdSZ8q4c". 
      "YTWvPj0giefVtMc7tV4c6AAw04jyIfmCTvcQUlHI+sspHxXDlQTagNoxCuA29b5L". 
      "9MKO6Ok0LwF9rGgTywC1heNEulZz9ISn9FQDazJT+Bd9cnNOrJRdAgMBAAE=". 
      "-----END RSA PUBLIC KEY----- 

, а затем я закодирован его в base64 и получил этот base64 закодированного ключ

LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tTUlHSkFvR0JBS2tzNjJJdG5zMnVVL2RWWko0a0NrTWluSGd5ZWgvcmRNRDUzYTRadTJhNzZPSUp2ZFNaOHE0Y1lUV3ZQajBnaWVmVnRNYzd0VjRjNkFBdzA0anlJZm1DVHZjUVVsSEkrc3NwSHhYRGxRVGFnTm94Q3VBMjliNUw5TUtPNk9rMEx3RjlyR2dUeXdDMWhlTkV1bFp6OUlTbjlGUURhekpUK0JkOWNuTk9ySlJkQWdNQkFBRT0tLS0tLUVORCBSU0EgUFVCTElDIEtFWS0tLS0t 

я скопировал его андроид стороны для шифрования данных, используя его, но я получил InvalidKeySpecException

Android Side Код:

public static byte[] encrypt(String text) { 

     byte[] encodedPublicKey= Base64.decode("LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tTUlHSkFvR0JBS2tzNjJJdG5zMnVVL2RWWko0a0NrTWluSGd5ZWgvcmRNRDUzYTRadTJhNzZPSUp2ZFNaOHE0Y1lUV3ZQajBnaWVmVnRNYzd0VjRjNkFBdzA0anlJZm1DVHZjUVVsSEkrc3NwSHhYRGxRVGFnTm94Q3VBMjliNUw5TUtPNk9rMEx3RjlyR2dUeXdDMWhlTkV1bFp6OUlTbjlGUURhekpUK0JkOWNuTk9ySlJkQWdNQkFBRT0tLS0tLUVORCBSU0EgUFVCTElDIEtFWS0tLS0t", Base64.DEFAULT); 



    PublicKey publicKey=null; 
    KeyFactory keyFactory = null; 
    try { 
     keyFactory = KeyFactory.getInstance("RSA"); 
     X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedPublicKey); 
     publicKey = keyFactory.generatePublic(publicKeySpec); 

    } catch (NoSuchAlgorithmException e) { 
     e.printStackTrace(); 
    }catch (InvalidKeySpecException e) { 
     e.printStackTrace(); 
    } 


    byte[] cipherText = null; 
    try { 
     // get an RSA cipher object and print the provider 
     final Cipher cipher = Cipher.getInstance("RSA"); 
     // encrypt the plain text using the public key 
     cipher.init(Cipher.ENCRYPT_MODE, publicKey); 
     cipherText = cipher.doFinal(text.getBytes()); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    return cipherText; 
} 
+2

Согласно [DOCS] (http://docs.oracle.com/javase/7/docs/api/java/security/spec/X509EncodedKeySpec.html), X509EncodedKeySpec ожидает ASN.1 отформатирован ключ , тогда как вы передаете форматированный ключ [PEM] (https://en.wikipedia.org/wiki/Privacy-enhanced_Electronic_Mail). – adelphus

+1

Хе, двойное кодирование base64. Это действительно не имеет смысла. Вам нужно base64 для преобразования двоичного кода в текст; для base64 мало используется, если вход * уже является текстовым *, не согласны ли вы? Снимите верхний и нижний колонтитулы и посмотрите, работает ли это. –

+1

@MaartenBodewes: Это не сработает, потому что формат является более простым открытым ключом PKCS # 1, просто модулем и показателем. Java ожидает более сложного зверя SubjectPublicKeyInfo, известного как «X509EncodedKey» в Java-ese. –

ответ

1

Следующий код разбирает PEM, подает его к PKCS # 1 RSAPublicKey класс парсера от BouncyCastle, затем строит JCE RSAPublicKey по модулю и экспоненте. Остальное - обработка ошибок, сам ключ и основной метод, чтобы показать, что это работает.

Для Android вам может потребоваться использовать Spongy Castle.

package nl.owlstead.stackoverflow; 

import java.io.IOException; 
import java.io.StringReader; 
import java.security.KeyFactory; 
import java.security.NoSuchAlgorithmException; 
import java.security.interfaces.RSAPublicKey; 
import java.security.spec.InvalidKeySpecException; 
import java.security.spec.RSAPublicKeySpec; 

import org.bouncycastle.util.io.pem.PemObject; 
import org.bouncycastle.util.io.pem.PemReader; 

public final class RSAPublicKeyFromOpenSSL_PKCS1_PEM { 
    private static final String PEM = "-----BEGIN RSA PUBLIC KEY-----\r\n" 
      + "MIGJAoGBAKks62Itns2uU/dVZJ4kCkMinHgyeh/rdMD53a4Zu2a76OIJvdSZ8q4c\r\n" 
      + "YTWvPj0giefVtMc7tV4c6AAw04jyIfmCTvcQUlHI+sspHxXDlQTagNoxCuA29b5L\r\n" 
      + "9MKO6Ok0LwF9rGgTywC1heNEulZz9ISn9FQDazJT+Bd9cnNOrJRdAgMBAAE=\r\n" 
      + "-----END RSA PUBLIC KEY-----\r\n"; 

    public static RSAPublicKey parsePEM(final String pem) 
      throws IllegalArgumentException { 

     // --- read PEM object 
     final PemObject readPemObject; 
     try (final PemReader reader = new PemReader(new StringReader(PEM))) { 
      readPemObject = reader.readPemObject(); 
     } catch (final IOException e) { 
      throw new IllegalArgumentException("Not a PEM object", e); 
     } 
     if (!readPemObject.getType().equalsIgnoreCase("RSA PUBLIC KEY")) { 
      throw new IllegalArgumentException("Not a public key"); 
     } 
     final byte[] pemContent = readPemObject.getContent(); 

     // --- create Bouncy Castle PKCS#1 public key 
     final org.bouncycastle.asn1.pkcs.RSAPublicKey pkcs1PublicKey; 
     try { 
      pkcs1PublicKey = org.bouncycastle.asn1.pkcs.RSAPublicKey 
        .getInstance(pemContent); 
     } catch (final Exception e) { 
      throw new IllegalArgumentException(
        "Could not parse BER PKCS#1 public key structure", e); 
     } 

     // --- convert to JCE RSAPublicKey 
     final RSAPublicKeySpec spec = new RSAPublicKeySpec(
       pkcs1PublicKey.getModulus(), pkcs1PublicKey.getPublicExponent()); 
     final KeyFactory rsaKeyFact; 
     try { 
      rsaKeyFact = KeyFactory.getInstance("RSA"); 
     } catch (final NoSuchAlgorithmException e) { 
      throw new IllegalStateException("RSA KeyFactory should be available", e); 
     } 
     try { 
      return (RSAPublicKey) rsaKeyFact.generatePublic(spec); 
     } catch (InvalidKeySpecException e) { 
      throw new IllegalArgumentException(
        "Invalid RSA public key, modulus and/or exponent invalid", e); 
     } 
    } 

    public static void main(final String ... args) throws Exception { 
     final RSAPublicKey publicKey = parsePEM(PEM); 
     System.out.println(publicKey); 
    } 
} 
+0

Можно также предварить открытый ключ с правильной структурой DER для создания 'SubjectPublicKey' и разобрать, что с помощью 'X509PublicKeySpec', но это работает, только если вы знаете точный размер ключа заранее, так что это более хрупкий код, чем этот. –

+0

Отвечает ли это на ваш вопрос, Халед? –