How can I fill in RSAParameters value in c#

2019-02-18 01:05发布

问题:

I was using below code for encryption in my project and everything was working fine.

RSACryptoServiceProvider x_alg = new RSACryptoServiceProvider(  );

// export only the public key 
RSAParameters x_public_params = x_alg.ExportParameters(false);

// export the private key 
RSAParameters x_private_params = x_alg.ExportParameters(true);

Now client changed the requirement and he want to store all the RSAParameters value into config file and provided below details for demo

<project name="netCard Server1">
  <key length="256"></key>
  <D length="64">00000000000000000000000000000000000000000000000000000000000019C5</D>
  <DP length="32">00000000000000000000000000000061</DP>
  <DQ length="32">00000000000000000000000000000065</DQ>
  <Exponent length="6">000DCD</Exponent>
  <InverseQ length="32">0000000000000000000000000000003B</InverseQ>
  <Modulus length="64">0000000000000000000000000000000000000000000000000000000000002C95</Modulus>
  <P length="32">00000000000000000000000000000065</P>
  <Q length="32">00000000000000000000000000000071</Q>
  <text length ="64">0123456789ABCDEF111111111111111125FE2222222222222233333333334444</text>
  <cipher length ="64">0000000000000000000000000000000000000000000000000000000000000000</cipher>
</project>

Now,the problem is that when I am importing the RSAParameters value,I am getting Bad Data Exception

回答1:

The problem that you have is that the XML that your customer has given you is not in the format required to deserialize to an object of type RSAParameters

I've run this code to show what the XML generated by the XML serializer looks like

var provider = new RSACryptoServiceProvider();

var parameters = provider.ExportParameters(true);

var x = new XmlSerializer(parameters.GetType());
x.Serialize(Console.Out, parameters);
Console.WriteLine();

The output that it generates is something like:

<RSAParameters>
  <Exponent>AQAB</Exponent>
  <Modulus>ruCEpD3XnR...g/waE=</Modulus>
  <P>90amUU3dDazsqN9+...jJUQ==</P>
  <Q>tQv5hGehNLLmv4aC...NfUQ==</Q>
  <DP>azJiiZ6itPoBQph...zBcQ==</DP>
  <DQ>OmewiOw9bxi/o82...f44Q==</DQ>
  <InverseQ>wNohk0NNl...YDg==</InverseQ>
  <D>fNOOWp46FckcvtI+...PpXAE=</D>
</RSAParameters>

where the ... is truncated output. What your customer has supplied looks like a superset of that (key, text and cipher are not in the parameter list) but the format is a bit different.

You can either ask them to supply the data in exactly the required format then serialize from that; or you can accept their format, deserialize it to XML and build the RSAParameters object manually by mapping the XML content to the appropriate fields on the RSAParameters object. You also need to work out what it is that they want to do with the key, text and cipher data as these will be lost in this process.



回答2:

From the sample structure you've provided it looks like there is extra data there, which you may (or may not) be able to provide.

  • create a wrapper class
  • wrapper properties to call conversion function to transform the Base64 to Hex
  • XmlElement attributes to control the output format
  • Cipher and Text are not in RSAProperties, so client will have to spec them for you

    [XmlRoot("Project")] public class RSAWrapper{ [XmlIgnore] public RSAParameters RsaWrap{get;set;}

    // replicate Key for Text and Cipher, subject to client's specs
    private LenghtyValue _key = null; 
    [XmlElement]
    public LenghtyValue Key{
        get{ return (_key!=null) ? _key.Value : null;}
        set{ _key = (value!=null) ? new LenghtyValue { Value = value} : null;}
    }
    
    
    // replicate Exponent for D, DP, DQ, InverseQ, Modulus, P and Q
    [XmlElement]
    public LenghtyValue Exponent{
       get{
           return new LenghtyValue { Value = ToHexFromB64(RsaWrap.Exponent);} // look up how to convert this
       }
       set {}
    } 
    
    public class LenghtyValue{
        [XmlText]
        public string Value{get;set;}
    
        [XmlAttribute("length")]
        public int Length {get{ return (""+Value").Length;} set{}}
    }
    

    }

// then use the class above as such: .... RSACryptoServiceProvider x_alg = new RSACryptoServiceProvider();

RSAParameters x_public_params = x_alg.ExportParameters(false); // or true

RSAWrapper wrapForClient = new RSAWrapper {
    RsaWrap = x_public_params,
    Key = "1024", // or whatever size you have
    Cipher = "???", // whatever this field means per client specs
    Text = "???", // whatever this field means per client specs
}

// with simplifications....
XmlSerializer xser = new XmlSerializer(typeof(RSAWrapper));
xser.Serialize(File.Create(yourFileName), wrapForClient);