How to convert B4A RSA key into .Net RSA key?

dreamworld

Active Member
Licensed User
Longtime User
The B4A RSA key is in format ot byte array, while the .Net RSA key is in XML format.
When an Android client program connects to a .Net server program, they have to exchange RSA public keys, but their RSA public keys are in different format.
How to convert one into another?

Example of .Net RSA public key:
<RSAKeyValue>
<Modulus>
upVkIXZywpuL6VLDpmCTbFC9YU8ShE1i/xZZNl90izs9tdw+ZesQmvtlhjA2WCbCHoh1SSANXQFFHqEU883dQzmA2lBZKhwQpfoz4lCylR/qxdbH+qlIwUzRVai+LY9eqHsqHchV2gnOiHKvmbrxVlOl8pykh0z2ADebuOGpDKc=</Modulus>
<Exponent>AQAB</Exponent>
</RSAKeyValue>
 

dreamworld

Active Member
Licensed User
Longtime User
When RSA keysize is set to 1024, the B4A RSA public key has 162 bytes and the text between <Modulus> of .Net RSA public key has 172 letter.
 
Upvote 0

dreamworld

Active Member
Licensed User
Longtime User
Can author of Encryption library add the following codes into his library?

// --- Returns XML encoded RSA public key string suitable for .NET
// CryptoServiceProvider.FromXmlString(true) ------
// --- Leading zero bytes (most significant) must be removed for XML
// encoding for .NET; otherwise format error ---

private String getRSAPublicKeyAsNetFormat(byte[] encodedPrivkey) {
try {
StringBuffer buff = new StringBuffer(1024);

PKCS8EncodedKeySpec pvkKeySpec = new PKCS8EncodedKeySpec(
encodedPrivkey);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPrivateCrtKey pvkKey = (RSAPrivateCrtKey) keyFactory
.generatePrivate(pvkKeySpec);
buff.append("<RSAKeyValue>");
buff.append("<Modulus>"
+ b64encode(removeMSZero(pvkKey.getModulus().toByteArray()))
+ "</Modulus>");
buff.append("<Exponent>"
+ b64encode(removeMSZero(pvkKey.getPublicExponent()
.toByteArray())) + "</Exponent>");
buff.append("</RSAKeyValue>");
return buff.toString().replaceAll("[ \t\n\r]", "");
} catch (Exception e) {
System.err.println(e);
return null;
}
}
 
Upvote 0

dreamworld

Active Member
Licensed User
Longtime User
// --------- remove leading (Most Significant) zero byte if present
// ----------------
private byte[] removeMSZero(byte[] data) {
byte[] data1;
int len = data.length;
if (data[0] == 0) {
data1 = new byte[data.length - 1];
System.arraycopy(data, 1, data1, 0, len - 1);
} else
data1 = data;

return data1;
}
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Because it takes the page title and it fails to correctly fetch the Chinese(?) characters.

You can implement it yourself with the Encryption library. Or if you like you can take the following Java code and convert it to a library:
B4X:
package test;

import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;

import anywheresoftware.b4a.BA.ActivityObject;
import anywheresoftware.b4a.BA.DependsOn;
import anywheresoftware.b4a.BA.Events;
import anywheresoftware.b4a.BA.ShortName;
import anywheresoftware.b4a.objects.StringUtils;


@ShortName("Test")
public class test{
   public String GetRSAPublicKeyAsNetFormat(byte[] encodedPrivkey) throws InvalidKeySpecException, NoSuchAlgorithmException {
         StringBuffer buff = new StringBuffer(1024);

         PKCS8EncodedKeySpec pvkKeySpec = new PKCS8EncodedKeySpec(
               encodedPrivkey);
         KeyFactory keyFactory = KeyFactory.getInstance("RSA");
         RSAPrivateCrtKey pvkKey = (RSAPrivateCrtKey) keyFactory
         .generatePrivate(pvkKeySpec);
         buff.append("<RSAKeyValue>");
         buff.append("<Modulus>"
               + b64encode(removeMSZero(pvkKey.getModulus().toByteArray()))
               + "</Modulus>");
         buff.append("<Exponent>"
               + b64encode(removeMSZero(pvkKey.getPublicExponent()
                     .toByteArray())) + "</Exponent>");
         buff.append("</RSAKeyValue>");
         return buff.toString().replaceAll("[ \t\n\r]", "");
   }
   private String b64encode(byte[] data) {
      StringUtils su = new StringUtils();
      return su.EncodeBase64(data);
   }
   private byte[] removeMSZero(byte[] data) {
      byte[] data1;
      int len = data.length;
      if (data[0] == 0) {
         data1 = new byte[data.length - 1];
         System.arraycopy(data, 1, data1, 0, len - 1);
      } else
         data1 = data;

      return data1;
   }
}

You should save it in a file named test.java under src\test. You should put StringUtils.jar from the libraries folder in the libs folder and compile it with SLC tool.
In your project you will need to reference StringUtils and this library.
 
Upvote 0

dreamworld

Active Member
Licensed User
Longtime User
Well, I can do that by myself.
But I think that author of Encryption library should add this function into his library.
 
Upvote 0
Top