Advertisement
Guest User

Untitled

a guest
Nov 26th, 2016
2,265
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 32.31 KB | None | 0 0
  1. /*
  2. Copyright (c) 2000  JavaScience Consulting,  Michel Gallant
  3.  
  4. Permission is hereby granted, free of charge, to any person obtaining a copy
  5. of this software and associated documentation files (the "Software"), to deal
  6. in the Software without restriction, including without limitation the rights
  7. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. copies of the Software, and to permit persons to whom the Software is
  9. furnished to do so, subject to the following conditions:
  10.  
  11. The above copyright notice and this permission notice shall be included in
  12. all copies or substantial portions of the Software.
  13.  
  14. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. THE SOFTWARE.
  21. */
  22. using System;
  23. using System.Collections.Generic;
  24. using System.Security.Cryptography;
  25. using System.IO;
  26. using System.Globalization;
  27.  
  28. namespace RSAKeyTests
  29. {
  30.     public class RSAKeyUtils
  31.     {
  32.         #region PUBLIC KEY TO X509 BLOB
  33.         internal static byte[] PublicKeyToX509(RSAParameters publicKey)
  34.         {
  35.  
  36.             /* *
  37.             * SEQUENCE                          * +- SEQUENCE                       *    +- OID                         *    +- Null                        * +- BITSTRING                      *    +- SEQUENCE                    *       +- INTEGER(N)               *       +- INTEGER(E)               * */
  38.  
  39.             AsnType oid = CreateOid("1.2.840.113549.1.1.1");
  40.             AsnType algorithmID =
  41.               CreateSequence(new AsnType[] { oid, CreateNull() });
  42.  
  43.             AsnType n = CreateIntegerPos(publicKey.Modulus);
  44.             AsnType e = CreateIntegerPos(publicKey.Exponent);
  45.             AsnType key = CreateBitString(
  46.               CreateSequence(new AsnType[] { n, e })
  47.             );
  48.  
  49.             AsnType publicKeyInfo =
  50.               CreateSequence(new AsnType[] { algorithmID, key });
  51.  
  52.             return new AsnMessage(publicKeyInfo.GetBytes(), "X.509").GetBytes();
  53.         }
  54.         #endregion BLOB
  55.  
  56.         #region PRIVATE KEY TO PKCS8 BLOB
  57.  
  58.         internal static byte[] PrivateKeyToPKCS8(RSAParameters privateKey)
  59.         {
  60.             AsnType n = CreateIntegerPos(privateKey.Modulus);
  61.             AsnType e = CreateIntegerPos(privateKey.Exponent);
  62.             AsnType d = CreateIntegerPos(privateKey.D);
  63.             AsnType p = CreateIntegerPos(privateKey.P);
  64.             AsnType q = CreateIntegerPos(privateKey.Q);
  65.             AsnType dp = CreateIntegerPos(privateKey.DP);
  66.             AsnType dq = CreateIntegerPos(privateKey.DQ);
  67.             AsnType iq = CreateIntegerPos(privateKey.InverseQ);
  68.  
  69.             AsnType version = CreateInteger(new byte[] { 0 });
  70.  
  71.             AsnType key = CreateOctetString(
  72.   CreateSequence(new AsnType[] { version, n, e, d, p, q, dp, dq, iq })
  73. );
  74.  
  75.             AsnType algorithmID = CreateSequence(new AsnType[] { CreateOid("1.2.840.113549.1.1.1"), CreateNull() }
  76. );
  77.  
  78.             AsnType privateKeyInfo =
  79.   CreateSequence(new AsnType[] { version, algorithmID, key });
  80.  
  81.             return new AsnMessage(privateKeyInfo.GetBytes(), "PKCS#8").GetBytes();
  82.         }
  83.         #endregion
  84.  
  85.         #region X509 PUBLIC KEY BLOB TO RSACRYPTOPROVIDER
  86.         internal static RSACryptoServiceProvider DecodePublicKey(byte[] publicKeyBytes)
  87.         {
  88.             MemoryStream ms = new MemoryStream(publicKeyBytes);
  89.             BinaryReader rd = new BinaryReader(ms);
  90.             byte[] SeqOID = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };
  91.             byte[] seq = new byte[15];
  92.  
  93.             try
  94.             {
  95.                 byte byteValue;
  96.                 ushort shortValue;
  97.  
  98.                 shortValue = rd.ReadUInt16();
  99.  
  100.                 switch (shortValue)
  101.                 {
  102.                     case 0x8130:
  103.                         rd.ReadByte(); break;
  104.                     case 0x8230:
  105.                         rd.ReadInt16(); break;
  106.                     default:
  107.                         return null;
  108.                 }
  109.  
  110.                 seq = rd.ReadBytes(15); if (!Helpers.CompareBytearrays(seq, SeqOID)) return null;
  111.  
  112.                 shortValue = rd.ReadUInt16();
  113.                 if (shortValue == 0x8103) rd.ReadByte();
  114.                 else if (shortValue == 0x8203)
  115.                     rd.ReadInt16();
  116.                 else
  117.                     return null;
  118.  
  119.                 byteValue = rd.ReadByte();
  120.                 if (byteValue != 0x00)
  121.                     return null;
  122.  
  123.                 shortValue = rd.ReadUInt16();
  124.                 if (shortValue == 0x8130) rd.ReadByte();
  125.                 else if (shortValue == 0x8230)
  126.                     rd.ReadInt16();
  127.                 else
  128.                     return null;
  129.  
  130.  
  131.                 CspParameters parms = new CspParameters();
  132.                 parms.Flags = CspProviderFlags.NoFlags;
  133.                 parms.KeyContainerName = Guid.NewGuid().ToString().ToUpperInvariant();
  134.                 parms.ProviderType = ((Environment.OSVersion.Version.Major > 5) || ((Environment.OSVersion.Version.Major == 5) && (Environment.OSVersion.Version.Minor >= 1))) ? 0x18 : 1;
  135.  
  136.                 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(parms);
  137.                 RSAParameters rsAparams = new RSAParameters();
  138.  
  139.                 rsAparams.Modulus = rd.ReadBytes(Helpers.DecodeIntegerSize(rd));
  140.  
  141.                 RSAParameterTraits traits = new RSAParameterTraits(rsAparams.Modulus.Length * 8);
  142.  
  143.                 rsAparams.Modulus = Helpers.AlignBytes(rsAparams.Modulus, traits.size_Mod);
  144.                 rsAparams.Exponent = Helpers.AlignBytes(rd.ReadBytes(Helpers.DecodeIntegerSize(rd)), traits.size_Exp);
  145.  
  146.                 rsa.ImportParameters(rsAparams);
  147.                 return rsa;
  148.             }
  149.             catch (Exception)
  150.             {
  151.                 return null;
  152.             }
  153.             finally
  154.             {
  155.                 rd.Close();
  156.             }
  157.         }
  158.  
  159.         #endregion
  160.  
  161.         #region PKCS8 PRIVATE KEY BLOB TO RSACRYPTOPROVIDER
  162.         public static RSACryptoServiceProvider DecodePrivateKeyInfo(byte[] pkcs8)
  163.         {
  164.             byte[] SeqOID = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };
  165.             byte[] seq = new byte[15];
  166.             MemoryStream mem = new MemoryStream(pkcs8);
  167.             int lenstream = (int)mem.Length;
  168.             BinaryReader binr = new BinaryReader(mem); byte bt = 0;
  169.             ushort twobytes = 0;
  170.  
  171.             try
  172.             {
  173.  
  174.                 twobytes = binr.ReadUInt16();
  175.                 if (twobytes == 0x8130) binr.ReadByte();
  176.                 else if (twobytes == 0x8230)
  177.                     binr.ReadInt16();
  178.                 else
  179.                     return null;
  180.  
  181.  
  182.                 bt = binr.ReadByte();
  183.                 if (bt != 0x02)
  184.                     return null;
  185.  
  186.                 twobytes = binr.ReadUInt16();
  187.  
  188.                 if (twobytes != 0x0001)
  189.                     return null;
  190.  
  191.                 seq = binr.ReadBytes(15); if (!CompareBytearrays(seq, SeqOID)) return null;
  192.  
  193.                 bt = binr.ReadByte();
  194.                 if (bt != 0x04) return null;
  195.  
  196.                 bt = binr.ReadByte(); if (bt == 0x81)
  197.                     binr.ReadByte();
  198.                 else
  199. if (bt == 0x82)
  200.                     binr.ReadUInt16();
  201.  
  202.                 byte[] rsaprivkey = binr.ReadBytes((int)(lenstream - mem.Position));
  203.                 RSACryptoServiceProvider rsacsp = DecodeRSAPrivateKey(rsaprivkey);
  204.                 return rsacsp;
  205.             }
  206.  
  207.             catch (Exception)
  208.             {
  209.                 return null;
  210.             }
  211.  
  212.             finally { binr.Close(); }
  213.  
  214.         }
  215.         #endregion
  216.  
  217.         #region UTIL CLASSES
  218.         private class Helpers
  219.         {
  220.             public static bool CompareBytearrays(byte[] a, byte[] b)
  221.             {
  222.                 if (a.Length != b.Length)
  223.                     return false;
  224.                 int i = 0;
  225.                 foreach (byte c in a)
  226.                 {
  227.                     if (c != b[i])
  228.                         return false;
  229.                     i++;
  230.                 }
  231.                 return true;
  232.             }
  233.             public static byte[] AlignBytes(byte[] inputBytes, int alignSize)
  234.             {
  235.                 int inputBytesSize = inputBytes.Length;
  236.  
  237.                 if ((alignSize != -1) && (inputBytesSize < alignSize))
  238.                 {
  239.                     byte[] buf = new byte[alignSize];
  240.                     for (int i = 0; i < inputBytesSize; ++i)
  241.                     {
  242.                         buf[i + (alignSize - inputBytesSize)] = inputBytes[i];
  243.                     }
  244.                     return buf;
  245.                 }
  246.                 else
  247.                 {
  248.                     return inputBytes;
  249.                 }
  250.             }
  251.  
  252.             public static int DecodeIntegerSize(System.IO.BinaryReader rd)
  253.             {
  254.                 byte byteValue;
  255.                 int count;
  256.  
  257.                 byteValue = rd.ReadByte();
  258.                 if (byteValue != 0x02) return 0;
  259.  
  260.                 byteValue = rd.ReadByte();
  261.                 if (byteValue == 0x81)
  262.                 {
  263.                     count = rd.ReadByte();
  264.                 }
  265.                 else if (byteValue == 0x82)
  266.                 {
  267.                     byte hi = rd.ReadByte(); byte lo = rd.ReadByte();
  268.                     count = BitConverter.ToUInt16(new[] { lo, hi }, 0);
  269.                 }
  270.                 else
  271.                 {
  272.                     count = byteValue;
  273.                 }
  274.  
  275.                 while (rd.ReadByte() == 0x00)
  276.                 {
  277.                     count -= 1;
  278.                 }
  279.                 rd.BaseStream.Seek(-1, System.IO.SeekOrigin.Current);
  280.  
  281.                 return count;
  282.             }
  283.         }
  284.  
  285.         private class RSAParameterTraits
  286.         {
  287.             public RSAParameterTraits(int modulusLengthInBits)
  288.             {
  289.                 int assumedLength = -1;
  290.                 double logbase = Math.Log(modulusLengthInBits, 2);
  291.                 if (logbase == (int)logbase)
  292.                 {
  293.                     assumedLength = modulusLengthInBits;
  294.                 }
  295.                 else
  296.                 {
  297.                     assumedLength = (int)(logbase + 1.0);
  298.                     assumedLength = (int)(Math.Pow(2, assumedLength));
  299.                     System.Diagnostics.Debug.Assert(false);
  300.                 }
  301.  
  302.                 switch (assumedLength)
  303.                 {
  304.                     case 512:
  305.                         this.size_Mod = 0x40;
  306.                         this.size_Exp = -1;
  307.                         this.size_D = 0x40;
  308.                         this.size_P = 0x20;
  309.                         this.size_Q = 0x20;
  310.                         this.size_DP = 0x20;
  311.                         this.size_DQ = 0x20;
  312.                         this.size_InvQ = 0x20;
  313.                         break;
  314.                     case 1024:
  315.                         this.size_Mod = 0x80;
  316.                         this.size_Exp = -1;
  317.                         this.size_D = 0x80;
  318.                         this.size_P = 0x40;
  319.                         this.size_Q = 0x40;
  320.                         this.size_DP = 0x40;
  321.                         this.size_DQ = 0x40;
  322.                         this.size_InvQ = 0x40;
  323.                         break;
  324.                     case 2048:
  325.                         this.size_Mod = 0x100;
  326.                         this.size_Exp = -1;
  327.                         this.size_D = 0x100;
  328.                         this.size_P = 0x80;
  329.                         this.size_Q = 0x80;
  330.                         this.size_DP = 0x80;
  331.                         this.size_DQ = 0x80;
  332.                         this.size_InvQ = 0x80;
  333.                         break;
  334.                     case 4096:
  335.                         this.size_Mod = 0x200;
  336.                         this.size_Exp = -1;
  337.                         this.size_D = 0x200;
  338.                         this.size_P = 0x100;
  339.                         this.size_Q = 0x100;
  340.                         this.size_DP = 0x100;
  341.                         this.size_DQ = 0x100;
  342.                         this.size_InvQ = 0x100;
  343.                         break;
  344.                     default:
  345.                         System.Diagnostics.Debug.Assert(false); break;
  346.                 }
  347.             }
  348.  
  349.             public int size_Mod = -1;
  350.             public int size_Exp = -1;
  351.             public int size_D = -1;
  352.             public int size_P = -1;
  353.             public int size_Q = -1;
  354.             public int size_DP = -1;
  355.             public int size_DQ = -1;
  356.             public int size_InvQ = -1;
  357.         }
  358.  
  359.  
  360.         private class AsnMessage
  361.         {
  362.             private byte[] m_octets;
  363.             private String m_format;
  364.  
  365.             internal int Length
  366.             {
  367.                 get
  368.                 {
  369.                     if (null == m_octets) { return 0; }
  370.                     return m_octets.Length;
  371.                 }
  372.             }
  373.  
  374.             internal AsnMessage(byte[] octets, String format)
  375.             {
  376.                 m_octets = octets;
  377.                 m_format = format;
  378.             }
  379.  
  380.             internal byte[] GetBytes()
  381.             {
  382.                 if (null == m_octets)
  383.                 { return new byte[] { }; }
  384.  
  385.                 return m_octets;
  386.             }
  387.             internal String GetFormat()
  388.             { return m_format; }
  389.         }
  390.  
  391.         private class AsnType
  392.         {
  393.  
  394.             public AsnType(byte tag, byte octet)
  395.             {
  396.                 m_raw = false;
  397.                 m_tag = new byte[] { tag };
  398.                 m_octets = new byte[] { octet };
  399.             }
  400.  
  401.             public AsnType(byte tag, byte[] octets)
  402.             {
  403.                 m_raw = false;
  404.                 m_tag = new byte[] { tag };
  405.                 m_octets = octets;
  406.             }
  407.  
  408.             public AsnType(byte tag, byte[] length, byte[] octets)
  409.             {
  410.                 m_raw = true;
  411.                 m_tag = new byte[] { tag };
  412.                 m_length = length;
  413.                 m_octets = octets;
  414.             }
  415.  
  416.             private bool m_raw;
  417.  
  418.             private bool Raw
  419.             {
  420.                 get { return m_raw; }
  421.                 set { m_raw = value; }
  422.             }
  423.  
  424.             private byte[] m_tag;
  425.             public byte[] Tag
  426.             {
  427.                 get
  428.                 {
  429.                     if (null == m_tag)
  430.                         return EMPTY;
  431.                     return m_tag;
  432.                 }
  433.             }
  434.  
  435.             private byte[] m_length;
  436.             public byte[] Length
  437.             {
  438.                 get
  439.                 {
  440.                     if (null == m_length)
  441.                         return EMPTY;
  442.                     return m_length;
  443.                 }
  444.             }
  445.  
  446.             private byte[] m_octets;
  447.             public byte[] Octets
  448.             {
  449.                 get
  450.                 {
  451.                     if (null == m_octets)
  452.                     { return EMPTY; }
  453.                     return m_octets;
  454.                 }
  455.                 set
  456.                 { m_octets = value; }
  457.             }
  458.  
  459.             internal byte[] GetBytes()
  460.             {
  461.                 if (true == m_raw)
  462.                 {
  463.                     return Concatenate(
  464.                       new byte[][] { m_tag, m_length, m_octets }
  465.                     );
  466.                 }
  467.  
  468.                 SetLength();
  469.  
  470.                 if (0x05 == m_tag[0])
  471.                 {
  472.                     return Concatenate(
  473.                       new byte[][] { m_tag, m_octets }
  474.                     );
  475.                 }
  476.  
  477.                 return Concatenate(
  478.                   new byte[][] { m_tag, m_length, m_octets }
  479.                 );
  480.             }
  481.  
  482.             private void SetLength()
  483.             {
  484.                 if (null == m_octets)
  485.                 {
  486.                     m_length = ZERO;
  487.                     return;
  488.                 }
  489.  
  490.                 if (0x05 == m_tag[0])
  491.                 {
  492.                     m_length = EMPTY;
  493.                     return;
  494.                 }
  495.  
  496.                 byte[] length = null;
  497.  
  498.                 if (m_octets.Length < 0x80)
  499.                 {
  500.                     length = new byte[1];
  501.                     length[0] = (byte)m_octets.Length;
  502.                 }
  503.                 else if (m_octets.Length <= 0xFF)
  504.                 {
  505.                     length = new byte[2];
  506.                     length[0] = 0x81;
  507.                     length[1] = (byte)((m_octets.Length & 0xFF));
  508.                 }
  509.  
  510.  
  511.                 else if (m_octets.Length <= 0xFFFF)
  512.                 {
  513.                     length = new byte[3];
  514.                     length[0] = 0x82;
  515.                     length[1] = (byte)((m_octets.Length & 0xFF00) >> 8);
  516.                     length[2] = (byte)((m_octets.Length & 0xFF));
  517.                 }
  518.  
  519.                 else if (m_octets.Length <= 0xFFFFFF)
  520.                 {
  521.                     length = new byte[4];
  522.                     length[0] = 0x83;
  523.                     length[1] = (byte)((m_octets.Length & 0xFF0000) >> 16);
  524.                     length[2] = (byte)((m_octets.Length & 0xFF00) >> 8);
  525.                     length[3] = (byte)((m_octets.Length & 0xFF));
  526.                 }
  527.                 else
  528.                 {
  529.                     length = new byte[5];
  530.                     length[0] = 0x84;
  531.                     length[1] = (byte)((m_octets.Length & 0xFF000000) >> 24);
  532.                     length[2] = (byte)((m_octets.Length & 0xFF0000) >> 16);
  533.                     length[3] = (byte)((m_octets.Length & 0xFF00) >> 8);
  534.                     length[4] = (byte)((m_octets.Length & 0xFF));
  535.                 }
  536.  
  537.                 m_length = length;
  538.             }
  539.  
  540.             private byte[] Concatenate(byte[][] values)
  541.             {
  542.                 if (IsEmpty(values))
  543.                     return new byte[] { };
  544.  
  545.                 int length = 0;
  546.                 foreach (byte[] b in values)
  547.                 {
  548.                     if (null != b) length += b.Length;
  549.                 }
  550.  
  551.                 byte[] cated = new byte[length];
  552.  
  553.                 int current = 0;
  554.                 foreach (byte[] b in values)
  555.                 {
  556.                     if (null != b)
  557.                     {
  558.                         Array.Copy(b, 0, cated, current, b.Length);
  559.                         current += b.Length;
  560.                     }
  561.                 }
  562.  
  563.                 return cated;
  564.             }
  565.         };
  566.  
  567.         #endregion
  568.  
  569.         #region UTIL METHODS
  570.  
  571.         private static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey)
  572.         {
  573.             byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;
  574.  
  575.             MemoryStream mem = new MemoryStream(privkey);
  576.             BinaryReader binr = new BinaryReader(mem); byte bt = 0;
  577.             ushort twobytes = 0;
  578.             int elems = 0;
  579.             try
  580.             {
  581.                 twobytes = binr.ReadUInt16();
  582.                 if (twobytes == 0x8130) binr.ReadByte();
  583.                 else if (twobytes == 0x8230)
  584.                     binr.ReadInt16();
  585.                 else
  586.                     return null;
  587.  
  588.                 twobytes = binr.ReadUInt16();
  589.                 if (twobytes != 0x0102) return null;
  590.                 bt = binr.ReadByte();
  591.                 if (bt != 0x00)
  592.                     return null;
  593.  
  594.  
  595.                 elems = GetIntegerSize(binr);
  596.                 MODULUS = binr.ReadBytes(elems);
  597.  
  598.                 elems = GetIntegerSize(binr);
  599.                 E = binr.ReadBytes(elems);
  600.  
  601.                 elems = GetIntegerSize(binr);
  602.                 D = binr.ReadBytes(elems);
  603.  
  604.                 elems = GetIntegerSize(binr);
  605.                 P = binr.ReadBytes(elems);
  606.  
  607.                 elems = GetIntegerSize(binr);
  608.                 Q = binr.ReadBytes(elems);
  609.  
  610.                 elems = GetIntegerSize(binr);
  611.                 DP = binr.ReadBytes(elems);
  612.  
  613.                 elems = GetIntegerSize(binr);
  614.                 DQ = binr.ReadBytes(elems);
  615.  
  616.                 elems = GetIntegerSize(binr);
  617.                 IQ = binr.ReadBytes(elems);
  618.  
  619.                 RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
  620.                 RSAParameters RSAparams = new RSAParameters();
  621.                 RSAparams.Modulus = MODULUS;
  622.                 RSAparams.Exponent = E;
  623.                 RSAparams.D = D;
  624.                 RSAparams.P = P;
  625.                 RSAparams.Q = Q;
  626.                 RSAparams.DP = DP;
  627.                 RSAparams.DQ = DQ;
  628.                 RSAparams.InverseQ = IQ;
  629.                 RSA.ImportParameters(RSAparams);
  630.                 return RSA;
  631.             }
  632.             catch (Exception)
  633.             {
  634.                 return null;
  635.             }
  636.             finally { binr.Close(); }
  637.         }
  638.  
  639.         private static int GetIntegerSize(BinaryReader binr)
  640.         {
  641.             byte bt = 0;
  642.             byte lowbyte = 0x00;
  643.             byte highbyte = 0x00;
  644.             int count = 0;
  645.             bt = binr.ReadByte();
  646.             if (bt != 0x02) return 0;
  647.             bt = binr.ReadByte();
  648.  
  649.             if (bt == 0x81)
  650.                 count = binr.ReadByte();
  651.             else
  652.             if (bt == 0x82)
  653.             {
  654.                 highbyte = binr.ReadByte(); lowbyte = binr.ReadByte();
  655.                 byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
  656.                 count = BitConverter.ToInt32(modint, 0);
  657.             }
  658.             else
  659.             {
  660.                 count = bt;
  661.             }
  662.  
  663.  
  664.  
  665.             while (binr.ReadByte() == 0x00)
  666.             {
  667.                 count -= 1;
  668.             }
  669.             binr.BaseStream.Seek(-1, SeekOrigin.Current); return count;
  670.         }
  671.  
  672.  
  673.         private static bool CompareBytearrays(byte[] a, byte[] b)
  674.         {
  675.             if (a.Length != b.Length)
  676.                 return false;
  677.             int i = 0;
  678.             foreach (byte c in a)
  679.             {
  680.                 if (c != b[i])
  681.                     return false;
  682.                 i++;
  683.             }
  684.             return true;
  685.         }
  686.  
  687.  
  688.  
  689.         private static AsnType CreateOctetString(byte[] value)
  690.         {
  691.             if (IsEmpty(value))
  692.             {
  693.                 return new AsnType(0x04, EMPTY);
  694.             }
  695.  
  696.             return new AsnType(0x04, value);
  697.         }
  698.  
  699.         private static AsnType CreateOctetString(AsnType value)
  700.         {
  701.             if (IsEmpty(value))
  702.             {
  703.                 return new AsnType(0x04, 0x00);
  704.             }
  705.  
  706.             return new AsnType(0x04, value.GetBytes());
  707.         }
  708.  
  709.         private static AsnType CreateOctetString(AsnType[] values)
  710.         {
  711.             if (IsEmpty(values))
  712.             {
  713.                 return new AsnType(0x04, 0x00);
  714.             }
  715.  
  716.             return new AsnType(0x04, Concatenate(values));
  717.         }
  718.  
  719.         private static AsnType CreateOctetString(String value)
  720.         {
  721.             if (IsEmpty(value))
  722.             { return CreateOctetString(EMPTY); }
  723.  
  724.             int len = (value.Length + 255) / 256;
  725.  
  726.             List<byte> octets = new List<byte>();
  727.             for (int i = 0; i < len; i++)
  728.             {
  729.                 String s = value.Substring(i * 2, 2);
  730.                 byte b = 0x00;
  731.  
  732.                 try
  733.                 { b = Convert.ToByte(s, 16); }
  734.                 catch (FormatException /*e*/) { break; }
  735.                 catch (OverflowException /*e*/) { break; }
  736.  
  737.                 octets.Add(b);
  738.             }
  739.  
  740.             return CreateOctetString(octets.ToArray());
  741.         }
  742.  
  743.         private static AsnType CreateBitString(byte[] octets)
  744.         {
  745.             return CreateBitString(octets, 0);
  746.         }
  747.  
  748.         private static AsnType CreateBitString(byte[] octets, uint unusedBits)
  749.         {
  750.             if (IsEmpty(octets))
  751.             {
  752.                 return new AsnType(0x03, EMPTY);
  753.             }
  754.  
  755.             if (!(unusedBits < 8))
  756.             { throw new ArgumentException("Unused bits must be less than 8."); }
  757.  
  758.             byte[] b = Concatenate(new byte[] { (byte)unusedBits }, octets);
  759.             return new AsnType(0x03, b);
  760.         }
  761.  
  762.         private static AsnType CreateBitString(AsnType value)
  763.         {
  764.             if (IsEmpty(value))
  765.             { return new AsnType(0x03, EMPTY); }
  766.  
  767.             return CreateBitString(value.GetBytes(), 0x00);
  768.         }
  769.  
  770.         private static AsnType CreateBitString(AsnType[] values)
  771.         {
  772.             if (IsEmpty(values))
  773.             { return new AsnType(0x03, EMPTY); }
  774.  
  775.             return CreateBitString(Concatenate(values), 0x00);
  776.         }
  777.  
  778.         private static AsnType CreateBitString(String value)
  779.         {
  780.             if (IsEmpty(value))
  781.             { return CreateBitString(EMPTY); }
  782.  
  783.             int lstrlen = value.Length;
  784.             int unusedBits = 8 - (lstrlen % 8);
  785.             if (8 == unusedBits) { unusedBits = 0; }
  786.  
  787.             for (int i = 0; i < unusedBits; i++)
  788.             { value += "0"; }
  789.  
  790.             int loctlen = (lstrlen + 7) / 8;
  791.  
  792.             List<byte> octets = new List<byte>();
  793.             for (int i = 0; i < loctlen; i++)
  794.             {
  795.                 String s = value.Substring(i * 8, 8);
  796.                 byte b = 0x00;
  797.  
  798.                 try
  799.                 { b = Convert.ToByte(s, 2); }
  800.  
  801.                 catch (FormatException /*e*/) { unusedBits = 0; break; }
  802.                 catch (OverflowException /*e*/) { unusedBits = 0; break; }
  803.  
  804.                 octets.Add(b);
  805.             }
  806.  
  807.             return CreateBitString(octets.ToArray(), (uint)unusedBits);
  808.         }
  809.  
  810.         private static byte[] ZERO = new byte[] { 0 };
  811.         private static byte[] EMPTY = new byte[] { };
  812.  
  813.         private static bool IsZero(byte[] octets)
  814.         {
  815.             if (IsEmpty(octets))
  816.             { return false; }
  817.  
  818.             bool allZeros = true;
  819.             for (int i = 0; i < octets.Length; i++)
  820.             {
  821.                 if (0 != octets[i])
  822.                 { allZeros = false; break; }
  823.             }
  824.             return allZeros;
  825.         }
  826.  
  827.         private static bool IsEmpty(byte[] octets)
  828.         {
  829.             if (null == octets || 0 == octets.Length)
  830.             { return true; }
  831.  
  832.             return false;
  833.         }
  834.  
  835.         private static bool IsEmpty(String s)
  836.         {
  837.             if (null == s || 0 == s.Length)
  838.             { return true; }
  839.  
  840.             return false;
  841.         }
  842.  
  843.         private static bool IsEmpty(String[] strings)
  844.         {
  845.             if (null == strings || 0 == strings.Length)
  846.                 return true;
  847.  
  848.             return false;
  849.         }
  850.  
  851.         private static bool IsEmpty(AsnType value)
  852.         {
  853.             if (null == value)
  854.             { return true; }
  855.  
  856.             return false;
  857.         }
  858.  
  859.         private static bool IsEmpty(AsnType[] values)
  860.         {
  861.             if (null == values || 0 == values.Length)
  862.                 return true;
  863.  
  864.             return false;
  865.         }
  866.  
  867.         private static bool IsEmpty(byte[][] arrays)
  868.         {
  869.             if (null == arrays || 0 == arrays.Length)
  870.                 return true;
  871.  
  872.             return false;
  873.         }
  874.  
  875.         private static AsnType CreateInteger(byte[] value)
  876.         {
  877.             if (IsEmpty(value))
  878.             { return CreateInteger(ZERO); }
  879.  
  880.             return new AsnType(0x02, value);
  881.         }
  882.  
  883.         private static AsnType CreateNull()
  884.         {
  885.             return new AsnType(0x05, new byte[] { 0x00 });
  886.         }
  887.  
  888.         private static byte[] Duplicate(byte[] b)
  889.         {
  890.             if (IsEmpty(b))
  891.             { return EMPTY; }
  892.  
  893.             byte[] d = new byte[b.Length];
  894.             Array.Copy(b, d, b.Length);
  895.  
  896.             return d;
  897.         }
  898.  
  899.         private static AsnType CreateIntegerPos(byte[] value)
  900.         {
  901.             byte[] i = null, d = Duplicate(value);
  902.  
  903.             if (IsEmpty(d)) { d = ZERO; }
  904.  
  905.             if (d.Length > 0 && d[0] > 0x7F)
  906.             {
  907.                 i = new byte[d.Length + 1];
  908.                 i[0] = 0x00;
  909.                 Array.Copy(d, 0, i, 1, value.Length);
  910.             }
  911.             else
  912.             {
  913.                 i = d;
  914.             }
  915.  
  916.             return CreateInteger(i);
  917.         }
  918.  
  919.         private static byte[] Concatenate(AsnType[] values)
  920.         {
  921.             if (IsEmpty(values))
  922.                 return new byte[] { };
  923.  
  924.             int length = 0;
  925.             foreach (AsnType t in values)
  926.             {
  927.                 if (null != t)
  928.                 { length += t.GetBytes().Length; }
  929.             }
  930.  
  931.             byte[] cated = new byte[length];
  932.  
  933.             int current = 0;
  934.             foreach (AsnType t in values)
  935.             {
  936.                 if (null != t)
  937.                 {
  938.                     byte[] b = t.GetBytes();
  939.  
  940.                     Array.Copy(b, 0, cated, current, b.Length);
  941.                     current += b.Length;
  942.                 }
  943.             }
  944.  
  945.             return cated;
  946.         }
  947.  
  948.         private static byte[] Concatenate(byte[] first, byte[] second)
  949.         {
  950.             return Concatenate(new byte[][] { first, second });
  951.         }
  952.  
  953.         private static byte[] Concatenate(byte[][] values)
  954.         {
  955.             if (IsEmpty(values))
  956.                 return new byte[] { };
  957.  
  958.             int length = 0;
  959.             foreach (byte[] b in values)
  960.             {
  961.                 if (null != b)
  962.                 { length += b.Length; }
  963.             }
  964.  
  965.             byte[] cated = new byte[length];
  966.  
  967.             int current = 0;
  968.             foreach (byte[] b in values)
  969.             {
  970.                 if (null != b)
  971.                 {
  972.                     Array.Copy(b, 0, cated, current, b.Length);
  973.                     current += b.Length;
  974.                 }
  975.             }
  976.  
  977.             return cated;
  978.         }
  979.  
  980.         private static AsnType CreateSequence(AsnType[] values)
  981.         {
  982.  
  983.             if (IsEmpty(values))
  984.             { throw new ArgumentException("A sequence requires at least one value."); }
  985.  
  986.             return new AsnType((0x10 | 0x20), Concatenate(values));
  987.         }
  988.  
  989.         private static AsnType CreateOid(String value)
  990.         {
  991.             if (IsEmpty(value))
  992.                 return null;
  993.  
  994.             String[] tokens = value.Split(new Char[] { ' ', '.' });
  995.  
  996.             if (IsEmpty(tokens))
  997.                 return null;
  998.  
  999.             UInt64 a = 0;
  1000.  
  1001.             List<UInt64> arcs = new List<UInt64>();
  1002.  
  1003.             foreach (String t in tokens)
  1004.             {
  1005.                 if (t.Length == 0) { break; }
  1006.  
  1007.                 try { a = Convert.ToUInt64(t, CultureInfo.InvariantCulture); }
  1008.                 catch (FormatException /*e*/) { break; }
  1009.                 catch (OverflowException /*e*/) { break; }
  1010.  
  1011.                 arcs.Add(a);
  1012.             }
  1013.  
  1014.             if (0 == arcs.Count)
  1015.                 return null;
  1016.  
  1017.             List<byte> octets = new List<byte>();
  1018.  
  1019.             if (arcs.Count >= 1) { a = arcs[0] * 40; }
  1020.             if (arcs.Count >= 2) { a += arcs[1]; }
  1021.             octets.Add((byte)(a));
  1022.  
  1023.             for (int i = 2; i < arcs.Count; i++)
  1024.             {
  1025.                 List<byte> temp = new List<byte>();
  1026.  
  1027.                 UInt64 arc = arcs[i];
  1028.  
  1029.                 do
  1030.                 {
  1031.                     temp.Add((byte)(0x80 | (arc & 0x7F)));
  1032.                     arc >>= 7;
  1033.                 } while (0 != arc);
  1034.  
  1035.                 byte[] t = temp.ToArray();
  1036.  
  1037.                 t[0] = (byte)(0x7F & t[0]);
  1038.  
  1039.                 Array.Reverse(t);
  1040.  
  1041.                 foreach (byte b in t)
  1042.                 { octets.Add(b); }
  1043.             }
  1044.  
  1045.             return CreateOid(octets.ToArray());
  1046.         }
  1047.  
  1048.         private static AsnType CreateOid(byte[] value)
  1049.         {
  1050.             if (IsEmpty(value))
  1051.             { return null; }
  1052.  
  1053.             return new AsnType(0x06, value);
  1054.         }
  1055.  
  1056.         private static byte[] Compliment1s(byte[] value)
  1057.         {
  1058.             if (IsEmpty(value))
  1059.             { return EMPTY; }
  1060.  
  1061.             byte[] c = Duplicate(value);
  1062.  
  1063.             for (int i = c.Length - 1; i >= 0; i--)
  1064.             {
  1065.                 c[i] = (byte)~c[i];
  1066.             }
  1067.  
  1068.             return c;
  1069.         }
  1070.  
  1071.         #endregion
  1072.     }
  1073. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement