不同平台生成的公钥的格式是不一样的,windows平台生成的公钥是Sun RSA public key,Android平台生成的公钥是OpenSSL public key。原因可能和JDK版本有关,windows平台使用的是SunJDK,Android平台使用的是OpenJDK。
Windows平台:
public class RSATest {
@Test
public void getPublicKey() {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
System.out.println(publicKey);
} catch (Exception e) {
}
}
}
RSA公钥如下:
Sun RSA public key, 1024 bits
modulus: 95213884349438225170527524041975750351683444678161946275254426695337973208253569775466173664279298747653058061430975492241277502919945076896996944444736550396126983267986003483379392361465058231916774917978538137429201243314904997369770567867017186086453893426267549310093584324574550363215845297101263978509
public exponent: 65537
Android平台:
public class RSATestOnAndroid {
@Test
public void getPublicKey() {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
Log.d("RSATest", "publicKey=" + publicKey);
} catch (Exception e) {
}
}
}
打印如下:
publicKey=OpenSSLRSAPublicKey{modulus=cbeecbec35b18cde50f2f201e441f5d9b57dacb2ba780a2f93152295d7661e822a570035e55217234d3f6070794faf28d5c3975fd62e1cfbf714cd379c8ee2166544a555e3f89c0be9074f8acccced9a9e1a8071a6c30abeea3bc5c8565dd34fd34794da50cb74e68c5f93e9f0925b60f87c89aacb25a9e357fd819ef0cf5a11,publicExponent=10001}
项目开发中遇到了如下问题:Windows服务器下发了RSA公钥,然后在Android平台上使用公钥来验证签名。很明显,Sun格式的公钥无法在Android平台上直接使用,需要进行转化。其实,windows平台的公钥是十进制的大数,而Android平台的公钥是16进制的大数,我们需要完成的工作就是进制的转化。
下面给出在Android平台上转化公钥中的 modulus 部分的方法(windows公钥 --> Android公钥):
import java.math.BigInteger;
public void convert(String modulusAtWindows) {
BigInteger 10Radix_bn = new BigInteger(modulusAtWindows, 10);
Log.d(TAG, "16RadixBitInteger=" + 10Radix_bn.toString(16));
}