简体   繁体   中英

How to verify a signature in .net generated in Android

The problem is the following:

  • I generate the key in 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; } 
  • Then i generate a signature:

      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(); 
  • And i send the key and the signature to a ASP.net wep API 2 server. Client side response generation:

      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; } 

I send it using Refit Nugget. And this is the code i use when i receive the HTTPRequest on server side:

[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);

    }

EVERY bool is wrong. I think the problem is clearly on the public key. The questions are,

  1. does the method publickey.encode() do what i think? I think it converts my public key to a byte[] representation (source: Android developer Key Info )

  2. do i convert the received byte[] representation of the key to a correct RSA key?

  3. Is there any problem on algorithms? I don't think so but we never know...

I don't find the solution. I searched for ways to import public keys from strings in .net or c# and for ways to export Android Public key to string or byte[] but there's no much help for this concrete questions...

@James K Polk gave me the solution. Apparently C# doesn't work well with PSS padding. I just had to change it to PKCS1. And i changed to digest algorithm too to SHA512.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM