저는 신입 회원입니다. 나는 안드로이드 클라이언트에서 파이썬 서버로 솔루션 검증 서명을 찾기 위해 이틀 동안 기다렸습니다. 먼저 키 쌍을 생성하고 개인 키로 서명을 생성합니다. 감사합니다 pedrofb 나는 전체 코드를 업데이 트했습니다. 파이썬 서버에서 완료 확인하십시오.안드로이드/파이썬 서명을 확인하는 방법 SHA256withRSA 및 PKCS1 패딩
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);
}
및 서버, 내가 서명을 확인하는 데 PKCS1_v1_5
를 사용, 그것은 안드로이드 클라이언트에서 전송됩니다
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."
나는 클라이언트와 서버, 그것의 동일한 해시 데이터를 확인해야하지만 false를 반환 verifier.verify , public.der
은 변수 PublicKeyStr
의 값이고 signature.der
은 변수의 값입니다 SignatureBase64
도와주세요. [코멘트 해결]
데이터는 *하지 * 같은, 그것은 자바에 "하하하"입니다 측면과 "하하"비단뱀 쪽. –
몇 가지 오류가 있습니다. 1) Java 코드와 서명 및 16 진수 값이 두 번 해시됩니다. 'signature.update (data.getBytes());'와'verifySignature.update (sha256 (data) .getBytes());와'signature.update (sha256 (data) .getBytes()); '.setBlockModes (KeyProperties.BLOCK_MODE_CBC)'를 제거하십시오. 3)'onCreate'가 호출 될 때마다 키 쌍을 만들어야합니다. – pedrofb
고맙지 만 클라이언트를 확인합니다. 사실, verifySignature 나는 그것이 안드로이드에서 작동 확인 만 만들면. 파이썬 측면과 자바 측 모두에 서명하는 데이터는 "haha"입니다. 파이썬에서 h.hexdigest()와 sha256 (데이터) .getBytes()는 같은 값을 반환합니다. – hai