本文介绍了密钥库操作失败,并带有RSA标志和验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 我很难使用RSA进行签名和验证。以下是我使用的 RSA 类的一部分。方法 init(), privateKey()和 publicKey()与 encrypt()和 decrypt()方法(最后两个未在此处列出)一起正常工作,所以我假设我在 sign()方法中犯了一些错误。尚未测试方法 verify(),因为签名不成功,所以我无法继续前进。请看看... I have difficulties to use RSA for signing and verifying. Below is part of my RSA class that I use. The methods init(), privateKey() and publicKey() work fine with encrypt() and decrypt() methods (last two not listed here), so I assume I made some mistake inside of my sign() method. Method verify() wasn't tested yet, because signing was unsuccessful, so I wasn't able to move further. Please take a look... 我的 RSA 类是:class RSA{ private final static String ANDROID_KEY_STORE = "AndroidKeyStore"; public final static int ANY_PURPOSE = KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT | KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY; public final static long CENTURY = (100 * 365) + 24; public enum KeySize { BIT_512 ( 512), BIT_768 ( 768), BIT_1024 (1024), BIT_2048 (2048), BIT_3072 (3072), BIT_4096 (4096); private int value; KeySize(int value) { this.value = value; } public int value() { return this.value; } } public enum SignatureAlgorithm { MD5WithRSA ("MD5WithRSA"), SHA1WithRSA ("SHA1WithRSA"), SHA1WithRSA_PSS ("SHA1WithRSA/PSS"), SHA224WithRSA ("SHA224WithRSA"), SHA224WithRSA_PSS ("SHA224WithRSA/PSS"), SHA256WithRSA ("SHA256WithRSA"), SHA256WithRSA_PSS ("SHA256WithRSA/PSS"), SHA384WithRSA ("SHA384WithRSA"), SHA384WithRSA_PSS ("SHA384WithRSA/PSS"), SHA512WithRSA ("SHA512WithRSA"), SHA512WithRSA_PSS ("SHA512WithRSA/PSS"); private String value; SignatureAlgorithm(String value) { this.value = value; } public String value() { return this.value; } } public static KeyPair init(final String alias, final RSA.KeySize keySize, final long validityDays, final Boolean reset) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, NoSuchProviderException, InvalidAlgorithmParameterException { KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE); keyStore.load(null); if (reset || (!keyStore.containsAlias(alias))) { final long now = java.lang.System.currentTimeMillis(); KeyPairGenerator keyPairGenerator = KeyPairGenerator .getInstance(KeyProperties.KEY_ALGORITHM_RSA, ANDROID_KEY_STORE); keyPairGenerator.initialize( new KeyGenParameterSpec.Builder(alias, RSA.ANY_PURPOSE) .setRandomizedEncryptionRequired(false) .setDigests( KeyProperties.DIGEST_NONE, KeyProperties.DIGEST_MD5, KeyProperties.DIGEST_SHA1, KeyProperties.DIGEST_SHA224, KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA384, KeyProperties.DIGEST_SHA512) .setKeySize(keySize.value()) .setEncryptionPaddings( KeyProperties.ENCRYPTION_PADDING_NONE, KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1, KeyProperties.ENCRYPTION_PADDING_RSA_OAEP) .setCertificateSubject(new X500Principal( "CN=Android, O=Android Authority")) .setCertificateSerialNumber(new BigInteger(256, new Random())) .setCertificateNotBefore(new Date (now - (now % 1000L))) .setCertificateNotAfter(new Date(((new Date(now - (now % 1000L))) .getTime()) + (validityDays * 86400000L))) .build()); return keyPairGenerator.generateKeyPair(); } else return null; } public static PublicKey publicKey(final String alias) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, UnrecoverableEntryException { KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE); keyStore.load(null); return keyStore.getCertificate(alias).getPublicKey(); } public static PrivateKey privateKey(final String alias) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, UnrecoverableEntryException { KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE); keyStore.load(null); return (PrivateKey) keyStore.getKey(alias, null); } public static byte[] sign(final String message, final String alias, final SignatureAlgorithm algorithm) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, UnrecoverableEntryException, InvalidKeyException, SignatureException { Signature instance = Signature.getInstance(algorithm.value()); instance.initSign(privateKey(alias), new SecureRandom()); instance.update(message.getBytes("UTF-8")); return instance.sign(); } public static Boolean verify(final String message, final byte[] signature, final String alias, final SignatureAlgorithm algorithm) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, UnrecoverableEntryException, InvalidKeyException, SignatureException { Signature instance = Signature.getInstance(algorithm.value()); instance.initVerify(publicKey(alias)); instance.update(message.getBytes("UTF-8")); return instance.verify(signature); }} 我的 Hex 类是:class Hex{ private final static char[] hexArray = "0123456789ABCDEF".toCharArray(); public static String bytesToHexString(final byte[] bytes) { char[] hexChars = new char[2 * bytes.length]; for (int i = 0; i < bytes.length; i++) { int b = bytes[i] & 0xFF; hexChars[2 * i] = hexArray[b >>> 4]; hexChars[2 * i + 1] = hexArray[b & 0x0F]; } return new String(hexChars); }} 我的测试代码是:My test code is:try{ RSA.init("RSA", RSA.KeySize.BIT_512, RSA.CENTURY, true); RSA.SignatureAlgorithm signatureAlgorithm = RSA.SignatureAlgorithm.SHA1WithRSA; byte[] x = RSA.sign("My message", "RSA", signatureAlgorithm); Log.d("RSA Test", "x: " + Hex.bytesToHexString(x)); Boolean y = RSA.verify("My message", x, "RSA", signatureAlgorithm); Log.d("RSA Test", "y: " + (y? "True" : "False"));}catch (Exception e){ Log.d("RSA Test", "ERROR: " + e.toString());} 输出为: And the output is:调试显示错误发生在我的 RSA.sign()方法内部,当它调用 initSign()。Debugging shows that the error occur inside of my RSA.sign() method, when it calls initSign().我的代码有什么问题? What is wrong in my code? 推荐答案如果您使用RSA密钥签名,则必须在 KeyGenParameterSpec 。您还没有这样做。例如,在您的 init()方法中,您可以在 .setEncryptionPaddings()之后添加以下行:If you are signing with an RSA key you must set a signature padding mode in the KeyGenParameterSpec. You haven't done so. For example, in your init() method you might add the following line right after .setEncryptionPaddings():.setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1)例如keyPairGenerator.initialize( new KeyGenParameterSpec.Builder(alias, RSA.ANY_PURPOSE) .setRandomizedEncryptionRequired(false) .setDigests( KeyProperties.DIGEST_NONE, KeyProperties.DIGEST_MD5, KeyProperties.DIGEST_SHA1, KeyProperties.DIGEST_SHA224, KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA384, KeyProperties.DIGEST_SHA512) .setKeySize(keySize.value()) .setEncryptionPaddings( KeyProperties.ENCRYPTION_PADDING_NONE, KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1, KeyProperties.ENCRYPTION_PADDING_RSA_OAEP) .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1) .setCertificateSubject(new X500Principal( "CN=Android, O=Android Authority")) .setCertificateSerialNumber(new BigInteger(256, new Random())) .setCertificateNotBefore(new Date(now - (now % 1000L))) .setCertificateNotAfter(new Date(((new Date(now - (now % 1000L))) .getTime()) + (validityDays * 86400000L))) .build());其他受支持的签名填充模式为 SIGNATURE_PADDING_RSA_PSS 。请注意,PSS签名和OAEP加密是用于签名和加密的RSA块格式的更新版本。它们提供了更好的安全性保证,并且应始终比其他方式优先使用,除非由于现有代码库的互操作性问题而无法使用它们。The other supported signature padding mode is SIGNATURE_PADDING_RSA_PSS. Note that PSS signatures and OAEP encryption are the more modern versions of RSA block formatting for signing and encrypting. They provide better security guarantees and should always be preferred over the other modes unless they cannot be used because of interoperability issues with existing code bases.签名算法名称以 PSS,例如 SHA224WithRSA_PSS 显然仅用于PSS填充,而其他仅用于PKCS1填充。The signature algorithm names that end in "PSS", e.g. SHA224WithRSA_PSS are obviously only for PSS padding, whereas the others are only for PKCS1 padding. 这篇关于密钥库操作失败,并带有RSA标志和验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 10-19 08:25