3 // Copyright (c) Microsoft Corporation. All rights reserved.
6 // <OWNER>[....]</OWNER>
13 namespace System.Security.Cryptography {
15 using System.Runtime.Serialization;
16 using System.Security.Util;
17 using System.Globalization;
18 using System.Diagnostics.Contracts;
20 // DSAParameters is serializable so that one could pass the public parameters
21 // across a remote call, but we explicitly make the private key X non-serializable
22 // so you cannot accidently send it along with the public parameters.
24 [System.Runtime.InteropServices.ComVisible(true)]
25 public struct DSAParameters {
31 [NonSerialized] public byte[] X;
36 [System.Runtime.InteropServices.ComVisible(true)]
37 public abstract class DSA : AsymmetricAlgorithm
40 // Extending this class allows us to know that you are really implementing
41 // an DSA key. This is required for anybody providing a new DSA key value
44 // The class provides no methods, fields or anything else. Its only purpose is
45 // as a heirarchy member for identification of the algorithm.
54 new static public DSA Create() {
56 return new System.Security.Cryptography.DSACryptoServiceProvider ();
58 return Create("System.Security.Cryptography.DSA");
62 new static public DSA Create(String algName) {
63 return (DSA) CryptoConfig.CreateFromName(algName);
66 abstract public byte[] CreateSignature(byte[] rgbHash);
68 abstract public bool VerifySignature(byte[] rgbHash, byte[] rgbSignature);
70 // We can provide a default implementation of FromXmlString because we require
71 // every DSA implementation to implement ImportParameters
72 // All we have to do here is parse the XML.
74 public override void FromXmlString(String xmlString) {
75 if (xmlString == null) throw new ArgumentNullException("xmlString");
76 Contract.EndContractBlock();
77 DSAParameters dsaParams = new DSAParameters();
78 Parser p = new Parser(xmlString);
79 SecurityElement topElement = p.GetTopElement();
81 // P is always present
82 String pString = topElement.SearchForTextOfLocalName("P");
83 if (pString == null) {
84 throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidFromXmlString","DSA","P"));
86 dsaParams.P = Convert.FromBase64String(Utils.DiscardWhiteSpaces(pString));
88 // Q is always present
89 String qString = topElement.SearchForTextOfLocalName("Q");
90 if (qString == null) {
91 throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidFromXmlString","DSA","Q"));
93 dsaParams.Q = Convert.FromBase64String(Utils.DiscardWhiteSpaces(qString));
95 // G is always present
96 String gString = topElement.SearchForTextOfLocalName("G");
97 if (gString == null) {
98 throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidFromXmlString","DSA","G"));
100 dsaParams.G = Convert.FromBase64String(Utils.DiscardWhiteSpaces(gString));
102 // Y is always present
103 String yString = topElement.SearchForTextOfLocalName("Y");
104 if (yString == null) {
105 throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidFromXmlString","DSA","Y"));
107 dsaParams.Y = Convert.FromBase64String(Utils.DiscardWhiteSpaces(yString));
110 String jString = topElement.SearchForTextOfLocalName("J");
111 if (jString != null) dsaParams.J = Convert.FromBase64String(Utils.DiscardWhiteSpaces(jString));
113 // X is optional -- private key if present
114 String xString = topElement.SearchForTextOfLocalName("X");
115 if (xString != null) dsaParams.X = Convert.FromBase64String(Utils.DiscardWhiteSpaces(xString));
117 // Seed and PgenCounter are optional as a unit -- both present or both absent
118 String seedString = topElement.SearchForTextOfLocalName("Seed");
119 String pgenCounterString = topElement.SearchForTextOfLocalName("PgenCounter");
120 if ((seedString != null) && (pgenCounterString != null)) {
121 dsaParams.Seed = Convert.FromBase64String(Utils.DiscardWhiteSpaces(seedString));
122 dsaParams.Counter = Utils.ConvertByteArrayToInt(Convert.FromBase64String(Utils.DiscardWhiteSpaces(pgenCounterString)));
123 } else if ((seedString != null) || (pgenCounterString != null)) {
124 if (seedString == null) {
125 throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidFromXmlString","DSA","Seed"));
127 throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidFromXmlString","DSA","PgenCounter"));
131 ImportParameters(dsaParams);
134 // We can provide a default implementation of ToXmlString because we require
135 // every DSA implementation to implement ImportParameters
136 // If includePrivateParameters is false, this is just an XMLDSIG DSAKeyValue
137 // clause. If includePrivateParameters is true, then we extend DSAKeyValue with
138 // the other (private) elements.
140 public override String ToXmlString(bool includePrivateParameters) {
141 // From the XMLDSIG spec, RFC 3075, Section 6.4.1, a DSAKeyValue looks like this:
143 <element name="DSAKeyValue">
147 <element name="P" type="ds:CryptoBinary"/>
148 <element name="Q" type="ds:CryptoBinary"/>
149 <element name="G" type="ds:CryptoBinary"/>
150 <element name="Y" type="ds:CryptoBinary"/>
151 <element name="J" type="ds:CryptoBinary" minOccurs="0"/>
153 <sequence minOccurs="0">
154 <element name="Seed" type="ds:CryptoBinary"/>
155 <element name="PgenCounter" type="ds:CryptoBinary"/>
161 // we extend appropriately for private component X
162 DSAParameters dsaParams = this.ExportParameters(includePrivateParameters);
163 StringBuilder sb = new StringBuilder();
164 sb.Append("<DSAKeyValue>");
166 sb.Append("<P>"+Convert.ToBase64String(dsaParams.P)+"</P>");
167 sb.Append("<Q>"+Convert.ToBase64String(dsaParams.Q)+"</Q>");
168 sb.Append("<G>"+Convert.ToBase64String(dsaParams.G)+"</G>");
169 sb.Append("<Y>"+Convert.ToBase64String(dsaParams.Y)+"</Y>");
170 // Add optional components if present
171 if (dsaParams.J != null) {
172 sb.Append("<J>"+Convert.ToBase64String(dsaParams.J)+"</J>");
174 if ((dsaParams.Seed != null)) { // note we assume counter is correct if Seed is present
175 sb.Append("<Seed>"+Convert.ToBase64String(dsaParams.Seed)+"</Seed>");
176 sb.Append("<PgenCounter>"+Convert.ToBase64String(Utils.ConvertIntToByteArray(dsaParams.Counter))+"</PgenCounter>");
179 if (includePrivateParameters) {
180 // Add the private component
181 sb.Append("<X>"+Convert.ToBase64String(dsaParams.X)+"</X>");
183 sb.Append("</DSAKeyValue>");
184 return(sb.ToString());
187 abstract public DSAParameters ExportParameters(bool includePrivateParameters);
189 abstract public void ImportParameters(DSAParameters parameters);