如何用 Public 密钥验证 ECDSA?
How to verify ECDSA with Public Key?
我有以下生成密钥和签署密码消息的方法。
public void generateKeys() {
try {
keyStore = KeyStore.getInstance(KEYSTORE_NAME);
keyStore.load(null);
if (!keyStore.containsAlias(KEY_NAME)) {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, KEYSTORE_NAME);
keyPairGenerator.initialize(
new KeyGenParameterSpec.Builder(KEY_NAME,
KeyProperties.PURPOSE_SIGN)
.setDigests(KeyProperties.DIGEST_SHA256)
.setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
// Require the user to authenticate with a fingerprint to authorize
// every use of the private key
.setUserAuthenticationRequired(true)
.build());
keyPairGenerator.generateKeyPair();
}
loadKeys();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public BiometricPrompt.CryptoObject getCryptoObject() {
cryptoObject = new BiometricPrompt.CryptoObject(signature);
return cryptoObject;
}
private void loadKeys() {
try {
keyStore = KeyStore.getInstance(KEYSTORE_NAME);
keyStore.load(null);
if (keyStore.containsAlias(KEY_NAME)) {
publicKey = keyStore.getCertificate(KEY_NAME).getPublicKey();
privateKey = (PrivateKey) keyStore.getKey(KEY_NAME, null);
signature = Signature.getInstance(Constants.SIGNATURE);
signature.initSign(privateKey);
}
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
}
public String sign(String inputStr) {
try {
Signature signature = cryptoObject.getSignature();
signature.update(inputStr.getBytes());
byte[] signedBytes = signature.sign();
String result = HexManager.bytesToHex(signedBytes);
Log.d("TAG", result);
return result;
} catch (SignatureException e) {
e.printStackTrace();
}
return null;
}
之后,我将签名的密码保存在共享首选项中。以后想用指纹验证的新密码验证保存的密码
这是我的验证方法:
public boolean verify(String inputStr, String savedStr) {
try {
Signature signature = cryptoObject.getSignature();
signature.initVerify(publicKey);
signature.update(inputStr.getBytes());
boolean isVerified = signature.verify(savedStr.getBytes());
return isVerified;
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (SignatureException e) {
e.printStackTrace();
}
return false;
}
但它总是 return 错误。
有人知道为什么吗?
在您的 sign()
方法中,您似乎返回了从 signature.sign()
方法获得的 byte[]
的 Hex
。如果这就是您保存为 savedStr
的内容。那么验证方法应该改变,将Hex
编码的字符串转换为byte[]
。您可以使用 HexManager.hexToBytes()
(或等效项)(如果存在)将 savedStr
转换为 byte[] savedStrBytes
。
public boolean verify(String inputStr, String savedStr) {
try {
byte[] savedStrBytes = HexManager.hexToByes(savedStr);
Signature signature = cryptoObject.getSignature();
signature.initVerify(publicKey);
signature.update(inputStr.getBytes());
boolean isVerified = signature.verify(savedStrBytes);
return isVerified;
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (SignatureException e) {
e.printStackTrace();
}
return false;
}
我有以下生成密钥和签署密码消息的方法。
public void generateKeys() {
try {
keyStore = KeyStore.getInstance(KEYSTORE_NAME);
keyStore.load(null);
if (!keyStore.containsAlias(KEY_NAME)) {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, KEYSTORE_NAME);
keyPairGenerator.initialize(
new KeyGenParameterSpec.Builder(KEY_NAME,
KeyProperties.PURPOSE_SIGN)
.setDigests(KeyProperties.DIGEST_SHA256)
.setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
// Require the user to authenticate with a fingerprint to authorize
// every use of the private key
.setUserAuthenticationRequired(true)
.build());
keyPairGenerator.generateKeyPair();
}
loadKeys();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public BiometricPrompt.CryptoObject getCryptoObject() {
cryptoObject = new BiometricPrompt.CryptoObject(signature);
return cryptoObject;
}
private void loadKeys() {
try {
keyStore = KeyStore.getInstance(KEYSTORE_NAME);
keyStore.load(null);
if (keyStore.containsAlias(KEY_NAME)) {
publicKey = keyStore.getCertificate(KEY_NAME).getPublicKey();
privateKey = (PrivateKey) keyStore.getKey(KEY_NAME, null);
signature = Signature.getInstance(Constants.SIGNATURE);
signature.initSign(privateKey);
}
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
}
public String sign(String inputStr) {
try {
Signature signature = cryptoObject.getSignature();
signature.update(inputStr.getBytes());
byte[] signedBytes = signature.sign();
String result = HexManager.bytesToHex(signedBytes);
Log.d("TAG", result);
return result;
} catch (SignatureException e) {
e.printStackTrace();
}
return null;
}
之后,我将签名的密码保存在共享首选项中。以后想用指纹验证的新密码验证保存的密码
这是我的验证方法:
public boolean verify(String inputStr, String savedStr) {
try {
Signature signature = cryptoObject.getSignature();
signature.initVerify(publicKey);
signature.update(inputStr.getBytes());
boolean isVerified = signature.verify(savedStr.getBytes());
return isVerified;
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (SignatureException e) {
e.printStackTrace();
}
return false;
}
但它总是 return 错误。
有人知道为什么吗?
在您的 sign()
方法中,您似乎返回了从 signature.sign()
方法获得的 byte[]
的 Hex
。如果这就是您保存为 savedStr
的内容。那么验证方法应该改变,将Hex
编码的字符串转换为byte[]
。您可以使用 HexManager.hexToBytes()
(或等效项)(如果存在)将 savedStr
转换为 byte[] savedStrBytes
。
public boolean verify(String inputStr, String savedStr) {
try {
byte[] savedStrBytes = HexManager.hexToByes(savedStr);
Signature signature = cryptoObject.getSignature();
signature.initVerify(publicKey);
signature.update(inputStr.getBytes());
boolean isVerified = signature.verify(savedStrBytes);
return isVerified;
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (SignatureException e) {
e.printStackTrace();
}
return false;
}