title: RSA algorithm on swift and java
body: <p>I need to generate public/private key for RSA algorithm on IOS device and send public key to server with encrypted text. Server must read public key and decrypt user message. </p>
  
  <p>I have code on swift:</p>
  
  <pre><code> func generateKeys(){
      var publicKey: SecKey?
      var privateKey: SecKey?
  
      let publicKeyAttr: [NSObject: NSObject] = [kSecAttrIsPermanent:true as NSObject, kSecAttrApplicationTag:"publicTag".data(using: String.Encoding.utf8)! as NSObject]
      let privateKeyAttr: [NSObject: NSObject] = [kSecAttrIsPermanent:true as NSObject, kSecAttrApplicationTag:"privateTag".data(using: String.Encoding.utf8)! as NSObject]
  
      var keyPairAttr = [NSObject: NSObject]()
      keyPairAttr[kSecAttrKeyType] = kSecAttrKeyTypeRSA
      keyPairAttr[kSecAttrKeySizeInBits] = 4096 as NSObject
      keyPairAttr[kSecPublicKeyAttrs] = publicKeyAttr as NSObject
      keyPairAttr[kSecPrivateKeyAttrs] = privateKeyAttr as NSObject
  
      _ = SecKeyGeneratePair(keyPairAttr as CFDictionary, &amp;publicKey, &amp;privateKey)
  
      var error:Unmanaged&lt;CFError&gt;?
      if #available(iOS 10.0, *) {
          if let cfdata = SecKeyCopyExternalRepresentation(publicKey!, &amp;error) {
              let data:Data = cfdata as Data
              let b64Key = data.base64EncodedString(options: .lineLength64Characters)
              print("public base 64 : \n\(b64Key)")
          }
          if let cfdata = SecKeyCopyExternalRepresentation(privateKey!, &amp;error) {
              let data:Data = cfdata as Data
              let b64Key = data.base64EncodedString(options: .lineLength64Characters)
              print("private base 64 : \n\(b64Key)")
          }
      }
      let encrypted = encryptBase64(text: "test", key: publicKey!)
      let decrypted = decpryptBase64(encrpted: encrypted, key: privateKey!)
  
      print("decrypted \(String(describing: decrypted))")
  
      self.dismiss(animated: true, completion: nil);
  }
  
  
  func encryptBase64(text: String, key: SecKey) -&gt; String {
      let plainBuffer = [UInt8](text.utf8)
      var cipherBufferSize : Int = Int(SecKeyGetBlockSize(key))
      var cipherBuffer = [UInt8](repeating:0, count:Int(cipherBufferSize))
  
      // Encrypto  should less than key length
      let status = SecKeyEncrypt(key, SecPadding.PKCS1, plainBuffer, plainBuffer.count, &amp;cipherBuffer, &amp;cipherBufferSize)
      if (status != errSecSuccess) {
          print("Failed Encryption")
      }
  
      let mudata = NSData(bytes: &amp;cipherBuffer, length: cipherBufferSize)
      return mudata.base64EncodedString()
  }
  
  func decpryptBase64(encrpted: String, key: SecKey) -&gt; String? {
      let data : NSData = NSData(base64Encoded: encrpted, options: .ignoreUnknownCharacters)!
      let count = data.length / MemoryLayout&lt;UInt8&gt;.size
      var array = [UInt8](repeating: 0, count: count)
      data.getBytes(&amp;array, length:count * MemoryLayout&lt;UInt8&gt;.size)
  
      var plaintextBufferSize = Int(SecKeyGetBlockSize(key))
      var plaintextBuffer = [UInt8](repeating:0, count:Int(plaintextBufferSize))
  
      let status = SecKeyDecrypt(key, SecPadding.PKCS1, array, plaintextBufferSize, &amp;plaintextBuffer, &amp;plaintextBufferSize)
  
      if (status != errSecSuccess) {
          print("Failed Decrypt")
          return nil
      }
      return NSString(bytes: &amp;plaintextBuffer, length: plaintextBufferSize, encoding: String.Encoding.utf8.rawValue)! as String
  }
  </code></pre>
  
  <p>This code returns public key in PKCS1. I found the library: <a href="https://github.com/soyersoyer/SwCrypt." rel="nofollow noreferrer">SwCrypt</a>
  This code helps me to convert PKCS1 into PKCS8 and read public key with java</p>
  
  <pre><code>SwKeyConvert.PublicKey.pemToPKCS1DER(publicKeyPEM)
  </code></pre>
  
  <p>But I can't decrypt user message. Can you help me with message decryption? I wrote small unit test.</p>
  
  <pre><code>import org.junit.Test;
  
  import javax.crypto.Cipher;
  import java.security.KeyFactory;
  import java.security.NoSuchAlgorithmException;
  import java.security.PublicKey;
  import java.security.spec.InvalidKeySpecException;
  import java.security.spec.X509EncodedKeySpec;
  import java.util.Base64;
  
  import static org.junit.Assert.assertNotNull;
  
  public class TestExample {
      String publicKeyContent = "MIMAAiMwDQYJKoZIhvcNAQEBBQADgwACDwAwggIKAoICAQC4K4zr1jTi4SSypXbrNeGd2HbYlrDRIPsPcL5a4JwGUKXwi+Rpf8Xh0D4dcRRH+Rtd5F66aqdGnhCBKtU5XsmlT+QssIggihI0iF3LEPsMlKapDrDdSbWmuitVDSSlulReMcN3hEUl8AzlNyu817snZtYESiFxm87QV6xZAcrWzvIdyiStBbngCT/v76tOZDX56IIRGoLMi3WND7538PqqYheh2+oZk05O+Bf5LZc6YteTRLLOSyIIxesoABo8tvaFyIo2ihMcnDRnGAzOMNTLXiQdj2scAMCVr3oiLpU48+Iw8ptOUBDQioW15FsYd3ugZhUX+/mFtMFsYkJyYjyG5HCqAs2/wm6eIjjy1QQwUF2hB8Z7sqyF5KrVZOv6Q7+pB83tT02ZXcDXCdsiP10G3sA4kjc/r9TuQHjCIwZa1LO4tPaO8qAzlROHIkQ4FhdaAM9U9DUq3nBywQLcEVQmXeH1OA1ve96QbMQoN+SRPh0Kq6W0U4TbzvMskQ7bePKDjiWP2fdtgSfrnOsyJaLi04n+hDsgiMfd4N9tauSMpCY6H9l7yYPc5Z+3qG2ANhteZGa7wT1OZoGLkZV0OurnA4xkzwcB7h0RVEvABB9dtl6S60FK1NELQy6sC/HCcivo9sJ+C1g2Sln+8qEdiju86X5ja5pGiRhJAxwSp2ZKgwIDAQAB";
      String encryptedMessage = "g81SOC9XOD9zq5qfyhkdP/7ronNb82g3ueDtEh711L43zPSgrFksLEdIud/1fiDcV6N97RD41vb/iXtCg2/Gu6XliEhCaoG28reetG1cBndKF9UzQw9cYChp54S1wnhBkAAZQ4Of3c77DtPBCL4gcgv2ilBTm7o+NR2wXunfJ7Olbbau+7C1pa+Qv/+sz45r4gJmQ1MfGjHtw9e/U/3vjL9BfCEPn9Mo2zAZhkI81S0Ewth+csHwb3YTlE8mtHni1fvLRVXjvHk+57U3keoYPZk+93ytFL6pqkWMk+9VbLuUFHXn1mpSMiEr9GRN6XKRvEbbPp5lI9WjwRvtWfmRm5gLY76QinTrPb0KJg7oWmEoQie5o9W6MOkD+8vYV/SkkLT855SB3O57QLKCZmlSPlccE6GWfglHhAwRwrcTDY1bO/xH38gvYYPaAJMtJKtOVrqGxNkIUPwCCkdBa9JQwDSyTYxeh8AxC0ACs9cYVjMPrmC9zIZuRbmcneIGSugtzMZmI9qbLtW1aMlWuGrVyVhJlcCZuTJXWyBgx8xj8coX9YwUXSi1A4dL/Hl5Sme+HhAQs7OcH6ZZpsPmIIozXxHgOMhUo8k++cWg6+pudSoB2tr4NhxX/ID2jd1ELsg1C6mbxaKaGgXwfU9w4ZngbRxGTBlKWXwUP/xBa5BARZ4=";
  
      @Test
      public void encryptTest() throws Exception {
          PublicKey publicKey = convertPublicKey(publicKeyContent);
          assertNotNull(publicKey);
  
          String s = decryptString(publicKey, encryptedMessage);
          assertNotNull(s);
      }
  
      private PublicKey convertPublicKey(String publicKey) throws RSAAlgorithmException {
          try {
              KeyFactory keyFactory = KeyFactory.getInstance("RSA");
              //generate public key
              byte[] publicBytes = Base64.getDecoder().decode(publicKey);
              X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicBytes);
              return keyFactory.generatePublic(keySpec);
          } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
              throw new RSAAlgorithmException("Unable to generate public key from string " + publicKey + " . " + e.getMessage());
          }
      }
  
      private String decryptString(PublicKey publicKey, String value) throws Exception {
          byte[] decodedBytes;
          try {
              Cipher c = Cipher.getInstance("RSA/ECB/PKCS1Padding");
              c.init(Cipher.DECRYPT_MODE, publicKey);
              decodedBytes = c.doFinal(value.getBytes());
          } catch (Exception e) {
              System.out.println("Error = " + e);
              throw new Exception(e);
          }
          return new String(decodedBytes);
      }
  }
  </code></pre>
  
  <p>I have next error:</p>
  
  <pre><code>java.lang.Exception: javax.crypto.IllegalBlockSizeException: Data must not be longer than 512 bytes
  </code></pre>