问题
I'm new member, I have waited two days to find solution verify signature from android client to python server. First I create Key pair and generate signature from private key. Thank you pedrofb I have updated full code. verify done in python server.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
KeyPairGenerator keyPairGenerator = null;
try {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
//keyStore.deleteEntry("key1");
keyPairGenerator = KeyPairGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");
try {
KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder("key1", KeyProperties.PURPOSE_SIGN)
.setKeySize(2048)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setDigests(KeyProperties.DIGEST_SHA256)
.setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1);
keyPairGenerator.initialize(builder.build());
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PrivateKey privateKey = (PrivateKey) keyStore.getKey("key1", null);
PublicKey publicKey = keyStore.getCertificate("key1").getPublicKey();
String publicKeyStr = Base64.encodeToString(publicKey.getEncoded(), Base64.NO_WRAP);
Log.d("Hahaha", publicKeyStr);
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
String data = "haha";
signature.update(data.getBytes());
byte[] signatureBytes = signature.sign();
String signatureBase64 = Base64.encodeToString(signatureBytes, Base64.NO_WRAP);
Log.d("Hahaha", signatureBase64);
Signature verifySignature = Signature.getInstance("SHA256withRSA");
verifySignature.initVerify(publicKey);
verifySignature.update(data.getBytes());
boolean isVerify = verifySignature.verify(Base64.decode(signatureBase64, Base64.NO_WRAP));
Log.d("Hahaha", isVerify + "");
} catch (Exception e) {
e.printStackTrace();
}
}
public static String sha256(String rawString){
MessageDigest shaDigest;
byte[] data;
try {
data = rawString.getBytes("UTF-8");
shaDigest = MessageDigest.getInstance("SHA-256");
} catch (Exception e) {
return null;
}
shaDigest.update(data);
return toHex(shaDigest.digest());
}
public static String toHex(byte[] tmp) {
char hexDigits[] =
{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
'e', 'f'};
int nBytesLen = tmp.length;
char str[] = new char[nBytesLen * 2];
int k = 0;
for (byte byte0 : tmp) {
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
return new String(str);
}
and Server, I use PKCS1_v1_5
to verify signature, it will be sent from android client
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
from base64 import b64decode
keyDER = b64decode(open('public.der').read())
key = RSA.importKey(keyDER)
message = "haha"
h = SHA256.new(message)
print h.hexdigest()
signature = b64decode(open('signature.der').read())
verifier = PKCS1_v1_5.new(key)
if verifier.verify(h, signature):
print "The signature is authentic."
else:
print "The signature is not authentic."
I have check data hashed both client and server, it's same, but verifier.verify return false, public.der
is value of variable PublicKeyStr
and signature.der
is value of variable SignatureBase64
Please help me.
回答1:
[Solved in comments] You have several errors in your Java code
1) In the Java code, you are digesting the message twice with SHA256 and signing an hex value, not the binary message.
In java, SHA256withRSA
performs several operations, first applies the SHA256 digest algorithm to the message and then applies the RSA PKCS # 1 v1.5 algorithm. In python (or in other languages) it can be done programmatically in two steps
Change
signature.update(sha256(data).getBytes());
verifySignature.update(sha256(data).getBytes());
with
signature.update(data.getBytes());
verifySignature.update(data.getBytes());
2) Remove .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
. This is an encryption parameter not appliable to digital signature
3) You should create the the keypair once, not each time onCreate
is called
来源:https://stackoverflow.com/questions/47749257/android-python-how-to-verify-signature-sha256withrsa-and-pkcs1-padding