如何在C#中填写RSAParameters值

7
我在我的项目中使用以下代码进行加密,一切正常。
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);

现在客户更改了要求,他希望将所有的RSAParameters值存储到配置文件中,并提供以下演示详细信息。

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

现在的问题是,当我导入RSAParameters值时,出现了“坏数据异常”。

只需使用RSACryptoServiceProvider直接创建自己的RSA密钥对,然后导出带有和不带有私钥的参数。现在将该输出与上述内容进行比较,以查看差异。 - President James K. Polk
2个回答

8
你面临的问题是你的客户给你的XML不符合反序列化为RSAParameters类型对象所需的格式。
我运行了这段代码以展示XML序列化器生成的XML长什么样。
var provider = new RSACryptoServiceProvider();

var parameters = provider.ExportParameters(true);

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

它生成的输出大致如下:
<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>

在这里“被截断的输出”是指仅显示一部分。而您的客户提供的数据似乎包含了更多(参数列表中不包括键、文本和密码),但格式有些不同。

您可以要求他们按照要求提供数据,然后从那里序列化;或者接受他们的格式,将其反序列化为 XML,并通过将 XML 内容映射到 RSAParameters 对象上适当的字段来手动构建该对象。同时,您还需要确定他们想要使用密钥、文本和密码数据做什么,因为这些数据将在此过程中丢失。


据我所见,您的客户已经在他们的XML文件中以十六进制格式提供了P、Q、DP、DQ、InverseA和D的值,因此您不需要生成任何内容,您只需要解析该文件并将这些值分配给新的RSAParameters对象上的适当参数即可。 - satnhak

2
从您提供的示例结构来看,似乎存在额外的数据,您可以(或者可能)提供它。
  • 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{}}
    }
    

    }

//然后可以像下面这样使用上述类: .... 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);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接