dongshaidu2456
dongshaidu2456
2018-01-11 13:39
浏览 242

在用GO语言加密的同时,如何在c#中解密RSA加密的字符串。 解码OAEP填充时发生错误

I have an application running on c# and another server application in go. I need to implement secure communication using rsa.
What i'am doing is I've initialized the RSA provider in my C# application and generated public key to extract Modulus and Exponent. Then concatenated the modulus (Hexadecimal) and exponent (int) and converted this string to Base64 string, send it to a GO endpoint.

Here is C# code snippet

public string ConvertToPublicKey()
    {
        CspParameters rsaParameters = GetCspParameters();
        RSACryptoServiceProvider provider = newRSACryptoServiceProvider(rsaParameters);
        string paramsXml = RsaProvider.ToXmlString(false);

        XDocument xDocument = XDocument.Parse(paramsXml);
        string modulus = xDocument.Descendants().FirstOrDefault(x => x.Name == "Modulus")?.Value ?? string.Empty;
        string exponent = xDocument.Descendants().FirstOrDefault(x => x.Name == "Exponent")?.Value ?? string.Empty;
        byte[] base64BytesOfModulus = Convert.FromBase64String(modulus);
        string hexaDecimalofModulus = BitConverter.ToString(base64BytesOfModulus).Replace("-", string.Empty);
        byte[] base64BytesOfExponent = Convert.FromBase64String(exponent);
        string hexadecimalOfExponent = BitConverter.ToString(base64BytesOfExponent).Replace("-", string.Empty);
        int intOfExponent = Convert.ToInt32(hexadecimalOfExponent, 16);
        byte[] publicKey = Encoding.UTF8.GetBytes($"{hexaDecimalofModulus};{intOfExponent}");
        return Convert.ToBase64String(publicKey);
    }

    private static CspParameters GetCspParameters()
    {
        const string containerName = "KeyContainer";
        return new CspParameters
        {
            KeyContainerName = containerName,
            Flags = CspProviderFlags.UseMachineKeyStore
        };
    }

At Go endpoint I received public key and modulus correctly. Then I encrypted the message using public key and sent it back to c# application in response after converting encrypted message byte[] to base64.

Here is GO code snippet

func GetLicenseInfo(responseWriter http.ResponseWriter,request*http.Request) 
    {
    encryptionKey := request.Header.Get("Authorization")
    var decodedStringBytes, errors = b64.StdEncoding.DecodeString(encryptionKey)
    if errors == nil {
        var decodedString = string(decodedStringBytes)
        result := strings.Split(decodedString, ";")
        modulus := new(big.Int)
        modulus.SetString(result[0], 16)
        exponent, exponentErrors := strconv.Atoi(result[1])
        if exponentErrors == nil {
            var someInfo = utils.GetInfo()
            var InfoInJson = ToJson(someInfo)
            publicKey := &rsa.PublicKey{N: modulus, E: exponent}
            var encryptedMessage, err = rsa.EncryptOAEP(sha256.New(),rand.Reader, publicKey,[]byte(InfoInJson), []byte(""))
            var response = b64.StdEncoding.EncodeToString(encryptedMessage)
            if err == nil {
                json.NewEncoder(responseWriter).Encode(response)
            }
        }

    }
}

func ToJson(model InfoModel) string {
    InfoInJson, errors := json.Marshal(model)
    if errors != nil {
        panic("An error occurred while serializing the response")
    }
    return string(InfoInJson)
}

When i received the response back in Base64 string i converted it to Byte[] and tried decrypting that with same instance of RSACryptoServiceProvider then it throws the following exception

Error occurred while decoding OAEP padding.

any help?

UPDATE for example here is the base64 string that i received in GO

QUQ2NDlFRTlCQTA3Q0IxNEI1MTNDMzczQzBBMjNBOEQyMDI5MkVGQTBFMjgyNUIyMEEyMzM1MEE3OTUyNjgyQ0Y3MEFBQjJBMTZGMzQyNTM4MkU2RDZBRjU5M0IxRTI2MTE0OEIyQkFFRTY3MUVDMTQ1NDk1NjBDRkNEQUNCQzI3RUUxNDRFODZDQUI4RDBDOUY2OENBNTUwNUMxQjZGQkVBQjQ0MTlBMjg3RDhBRjgxRDUyREY3MEM0RDZDQTA5MkREMzk5Q0NEODU5Q0FGQzAzQ0JEQ0JBQzgwOTg3NDY0NThBMkY4NEREOTc1QjU5QTJBMUNBNzQxQTBDNkQ2RDs2NTUzNw==

and here is what my GO app sent back

QuWpWdEPSJR+l9UJTkh+heJJ/NpPwhz/hVVu1VdKYdz37YGWWdKTj7Fc5lZ3A8p1WjtC4F+yieZCz0tEatCqTpRmm9g6Oioyjbtr9qGTxO/PE+GA33YyBe6nmMRe674SPePx/fg6l3nnfSZ4/+iLCV4bNgyNqFHCaXc7H4Snms8=

UPDATE 2 I've updated the code snippet and included the data types and here is the part that dscrypts the content received from GO end point

public byte[] Decrypt(byte[] encryptedData, RSAParameters rsaParameters)
    {
        RsaProvider.ImportParameters(rsaParameters);
        return RsaProvider.Decrypt(encryptedData, true);
    }

i receive a base64 string then i convert to byte[] using this

byte[] b = Convert.FromBase64String(responseString); byte[] decryptedBytes=crypto.Decrypt(b, crypto.RsaProvider.ExportParameters(false));

crypto is the instance of the class that contains decryption logic,instacne of RSACryptoServiceProvider and that method(ConvertToPublicKey) given above returning the public key

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • dongzhuo1880
    dongzhuo1880 2018-01-11 21:23
    已采纳

    After addressing comments by @bartonjs I've also changed response response from go to

    var encryptedMessage, err = rsa.EncryptOAEP(sha256.New(), rand.Reader, publicKey, []byte(licenseInformationJson), []byte(""))
    if err == nil {
        responseWriter.Write([]byte(encryptedMessage))
    }
    

    Notice []byte(encryptedMessage) byte stream sent from go to c# is slightly changed because encryptedMessage is []unint8. so you need to typecast encryptedMessage to []byte so that values are correctly mapped in c#.

    点赞 评论
  • donglu7286
    donglu7286 2018-01-11 15:18

    In go you have

    var encryptedMessage, err = rsa.EncryptOAEP(sha256.New(), ...
    

    Which I'll go ahead and assume is OAEP with SHA-2-256.

    In C# you have

    return RsaProvider.Decrypt(encryptedData, true);
    

    Which is OAEP with SHA-1.

    You need to abandon RSACryptoServiceProvider. If you switch to RSACng you can then decrypt it with

    using (RSA rsa = new RSACng())
    {
        rsa.ImportParameters(rsaParameters);
        return rsa.Decrypt(encryptedData, RSAEncryptionPadding.OaepSHA256);
    }
    

    And while I'm here:

    In ConvertToPublicKey you export the XML, parse the XML, and turn it into byte arrays. Why not just call ExportParameters(false) and extract the Modulus and Exponent byte arrays directly?

    点赞 评论

相关推荐