问题如下:
我在 Android (Xamarin.Droid) 中生成密钥:
public IPublicKey CreateKey(string keyID) { /*KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance( KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore"); keyPairGenerator.initialize( new KeyGenParameterSpec.Builder( "key1", KeyProperties.PURPOSE_SIGN) .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512) .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PSS) .build()); KeyPair keyPair = keyPairGenerator.generateKeyPair(); Signature signature = Signature.getInstance("SHA256withRSA/PSS"); signature.initSign(keyPair.getPrivate()); // The key pair can also be obtained from the Android Keystore any time as follows: KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); keyStore.load(null); PrivateKey privateKey = (PrivateKey)keyStore.getKey("key1", null); PublicKey publicKey = keyStore.getCertificate("key1").getPublicKey();*/ //App.Current.MainPage.DisplayAlert("Info", "Creating a new key pair", "Ok"); // UTILIZANDO RSA KeyPairGenerator kpg = KeyPairGenerator.GetInstance(KeyProperties.KeyAlgorithmRsa, KEYSTORE_NAME); kpg.Initialize( new KeyGenParameterSpec.Builder(keyID, KeyStorePurpose.Sign) .SetSignaturePaddings(KeyProperties.SignaturePaddingRsaPss) .SetDigests(KeyProperties.DigestSha1) .Build() ); KeyPair keyPair = kpg.GenerateKeyPair(); Log.Debug(TAG, "New key created for fingerprint authentication"); return keyPair.Public; }
然后我生成一个签名:
KeyStore.PrivateKeyEntry PKentry = (KeyStore.PrivateKeyEntry)_keystore.GetEntry(keyID, null); IPublicKey pk = (IPublicKey)PKentry.Certificate.PublicKey; //this.pk = pk; privKey = PKentry.PrivateKey; //cipher.Init(Cipher.EncryptMode, privKey); //byte[] output = cipher.DoFinal(Encoding.UTF8.GetBytes(input)); //String s = new string(cipher.DoFinal(input)); // signature Signature sig = Signature.GetInstance("SHA1withRSA/PSS"); sig.InitSign(privKey); byte[] inputDataToSign = Encoding.UTF8.GetBytes(input); sig.Update(inputDataToSign); byte[] signatureBytes = sig.Sign();
我将密钥和签名发送到 ASP.net wep API 2 服务器。客户端响应生成:
RegistrationResponse registrationResponse = new RegistrationResponse(); string fcparams = Utils.Base64Encode(JsonConvert.SerializeObject(finalChallengeParams)); registrationResponse.fcParams = fcparams; byte[] signedData = sign(fcparams, registrationRequest.username, facetID); registrationResponse.signedData = signedData; registrationResponse.Base64key = convertPublicKeyToString(publicKey); ... ... private string convertPublicKeyToString(IPublicKey publicKey) { string publicKeyString = Base64.EncodeToString(publicKey.GetEncoded(), 0); return publicKeyString; }
我使用 Refit Nugget 发送它。这是我在服务器端收到 HTTPRequest 时使用的代码:
[Route("regResponse/")]
[HttpPost]
public IHttpActionResult ProcessClientRegistrationResponse([FromBody] RegistrationResponse registrationResponse)
{
//byte[] publicKeyBytes = Convert.FromBase64String(registrationResponse.Base64key);
byte[] publicKeyBytes = registrationResponse.Base64key;
AsymmetricKeyParameter asymmetricKeyParameter = PublicKeyFactory.CreateKey(publicKeyBytes);
RsaKeyParameters rsaKeyParameters = (RsaKeyParameters)asymmetricKeyParameter;
RSAParameters rsaParameters = new RSAParameters();
rsaParameters.Modulus = rsaKeyParameters.Modulus.ToByteArrayUnsigned();
rsaParameters.Exponent = rsaKeyParameters.Exponent.ToByteArrayUnsigned();
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.ImportParameters(rsaParameters);
/*****/
string alg = rsa.SignatureAlgorithm;
byte[] signedData = registrationResponse.signedData;
byte[] fcParamsBytes = Encoding.UTF8.GetBytes(registrationResponse.fcParams);
RSACng rsaCng = new RSACng();
rsaCng.ImportParameters(rsaParameters);
SHA1Managed hash = new SHA1Managed();
byte[] hashedData;
hashedData = hash.ComputeHash(signedData);
/*********/
bool rsaCngDataOk1 = rsaCng.VerifyData(fcParamsBytes, signedData, HashAlgorithmName.SHA1, RSASignaturePadding.Pss);
bool rsaCngDataOk2 = rsaCng.VerifyData(fcParamsBytes, signedData, HashAlgorithmName.SHA1, RSASignaturePadding.Pss);
bool rsaCngDataOk3 = rsaCng.VerifyData(hashedData, signedData, HashAlgorithmName.SHA1, RSASignaturePadding.Pss);
bool rsaCngDataOk4 = rsaCng.VerifyData(hashedData, signedData, HashAlgorithmName.SHA1, RSASignaturePadding.Pss);
bool rsaCngHashOk1 = rsaCng.VerifyHash(hashedData, signedData, HashAlgorithmName.SHA1, RSASignaturePadding.Pss);
bool dataOK1 = rsa.VerifyData(fcParamsBytes, new SHA1CryptoServiceProvider(), signedData);
bool dataOk2 = rsa.VerifyData(fcParamsBytes, signedData, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
bool hashOk = rsa.VerifyHash(hashedData, CryptoConfig.MapNameToOID("SHA1"), signedData);
return Ok(true);
}
每个布尔值都是错误的。我认为问题显然出在公钥上。问题是,
方法 publickey.encode() 做我想的吗?我认为它将我的公钥转换为 byte[] 表示(来源:Android 开发人员 Key Info)
我是否将收到的密钥的字节 [] 表示形式转换为正确的 RSA 密钥?
算法有问题吗?我不这么认为,但我们永远不知道...
我找不到解决方案。我搜索了从 .net 或 c# 中的字符串导入公钥的方法,以及将 Android 公钥导出为字符串或字节 [] 的方法,但对于这个具体问题没有太大帮助......