我创建了生成RSA密钥对的python3应用程序。
from Crypto.PublicKey import RSA
print("--Private Key Generate--")
key = RSA.generate(2048)
private_key = key.export_key()
file_out = open("key/private.pem", "wb")
file_out.write(private_key)
file_out.close()
print("--Public Key Generate--")
public_key = key.publickey().export_key()
file_out_1 = open("key/receiver.pem", "wb")
file_out_1.write(public_key)
file_out_1.close()
print("key Generated")
我使用python对一些数据进行签名并创建签名。也已使用python成功验证。
def sign(data):
private_key = RSA.import_key(open('key/private.pem').read())
h = SHA256.new(data)
signature = base64.b64encode(pss.new(private_key).sign(h))
print("signature generate")
verify(data,signature)
return signature
def verify(recive_Data ,signature):
public_key = RSA.import_key(open('key/receiver.pem').read())
h = SHA256.new(recive_Data)
verifier = pss.new(public_key)
try:
verifier.verify(h, base64.b64decode(signature))
print("The signature is authentic")
except (ValueError, TypeError):
print ("The signature is not authentic.")
但是实际上,我在Android中的验证实现(最小SDK 23,目标SDK 29)。因此,我需要将此验证代码转换为Android。我尝试使用以下代码,但未通过验证。需要一些专家帮助。
public class SecurityHelper {
private static String getKey(InputStream filename) throws IOException {
// Read key from file
String strKeyPEM = "";
BufferedReader br = new BufferedReader(new InputStreamReader(filename));
String line;
while ((line = br.readLine()) != null) {
strKeyPEM += line + "\n";
}
br.close();
// System.out.println(strKeyPEM);
return strKeyPEM;
}
public static PublicKey getPublicKey(InputStream filename) throws IOException, GeneralSecurityException {
String publicKeyPEM = getKey(filename);
return getPublicKeyFromString(publicKeyPEM);
}
public static PublicKey getPublicKeyFromString(String key) throws IOException, GeneralSecurityException {
String publicKeyPEM = key;
publicKeyPEM = publicKeyPEM.replace("-----BEGIN PUBLIC KEY-----\n", "");
publicKeyPEM = publicKeyPEM.replace("-----END PUBLIC KEY-----", "");
System.out.println(publicKeyPEM);
byte[] encoded = Base64.decode(publicKeyPEM ,Base64.CRLF);
// System.out.println(encoded);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey pubKey = kf.generatePublic(new X509EncodedKeySpec(encoded));
System.out.println(pubKey);
return pubKey;
}
public static boolean verify(PublicKey publicKey, String message, String signature) throws SignatureException, NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException, InvalidAlgorithmParameterException {
Signature sign = Signature.getInstance("SHA256withRSA");
sign.initVerify(publicKey);
sign.update(message.getBytes("UTF-8"));
System.out.println(message);
return sign.verify(Base64.decode(signature,Base64.CRLF));
}
}
在Python代码PSS和Android代码Pkcs#1 v1.5中使用了不同的填充,请参见区别RFC 8017。用SHA256withRSA
替换Android代码SHA256withRSA/PSS
。
更新:
尽管API级别23+支持Android文档SHA256withRSA/PSS
,但API级别23抛出SHA256withRSA/PSS
(SHA256withRSA/PSS
),API级别24+则按指定的方式工作。
API级别23的可能的[[解决方法是使用InvalidKeyException
,然后必须将其作为依赖项包含在Android项目中(详细信息取决于IDE,例如Android Studio的No provider supports the provided key
):] >BouncyCastle
添加BC Provider之前,必须删除预安装的版本。使用的模式为here:
implementation 'org.bouncycastle:bcprov-jdk15on:1.64'
注意:SHA256withRSAandMGF1
(see section Signature Algorithms)是另一种可能性。在这里,不必删除预安装的BC Provider。架构为SHA256withRSAandMGF1
。