I'm working on a client/server system and I'm trying to do some basic encryption. When I connect to the server, I send a public key as an escaped string across the socket. I've verified that the string is identical on both ends, newlines and all.
On the client (Android), I'm able to use the public/private keys to successfully encrypt and decrypt a secret key (for testing purposes). However, the server fails right out of the gate when trying to decode the public key from a String to a byte[], with:
java.lang.IllegalArgumentException: Illegal base64 character a
which seems preposterous, as 'a' is absolutely a base64 character, if I understand correctly. The client and server use a shared library to handle all encryption, so the code is nearly identical. The only difference is encoding/decoding base64 Strings, since java.util.Base64 is unavailable on Android.
Shared class
public abstract class EasyCrypt {
...
public PublicKey loadPublicKey(String key64) throws GeneralSecurityException {
byte[] data = decode(key64); //Calls abstract methods, shown below
X509EncodedKeySpec spec = new X509EncodedKeySpec(data);
KeyFactory fact = KeyFactory.getInstance("RSA");
return fact.generatePublic(spec);
}
...
}
Client (Android) methods
import android.util.Base64;
public class ClientCrypt extends EasyCrypt {
@Override
protected byte[] decode(String s) {
return Base64.decode(s.getBytes(), Base64.DEFAULT); //Works perfectly
}
@Override
protected String encode(byte[] bytes) {
return Base64.encodeToString(bytes, Base64.DEFAULT);
}
}
Server (Linux) methods
import java.util.Base64;
public class ServerCrypt extends EasyCrypt{
@Override
public byte[] decode(String str){
return Base64.getDecoder().decode(str); //Throws IllegalArgumentException
}
@Override
public String encode(byte[] bytes){
return Base64.getEncoder().encodeToString(bytes);
}
}