/// <summary> /// What to do when the selection changes in the QR Code site list: /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void cmboExportSiteQR_SelectedIndexChanged(object sender, EventArgs e) { // Asbestos underpants: try { // Get the current selection of the combo box and make sure it // isn't empty: String site = (string)cmboExportSiteQR.Text; if (!String.IsNullOrEmpty(site)) { // Ask the main form to give us the site parameters for this site. // Since the main form has all the code to do this, we'll ask it // to do the dirty work. SiteParameters siteParams = caller.GetSiteParamsForQRCode(site); // Now we'll generate the text we'll embed into the QR Code. We want // this to be as compact as we can get it, so our "headings" will be // single letters. We'll start off with an identifying header so the // QR Code reader will know the format of our string. We delimite the // string with pipes, which aren't allowed in any of our fields. We // want this to match as closely to the values of the XML export file // for consistency. That means the hash engine and the character // limit fields will need some tweaking. StringBuilder sb = new StringBuilder(); sb.Append("CRYPTNOSv1|" + "S:" + siteParams.Site + "|" + "H:" + HashEngine.HashEnumStringToDisplayHash(siteParams.Hash) + "|" + "I:" + siteParams.Iterations.ToString() + "|" + "C:" + siteParams.CharTypes.ToString() + "|L:"); if (siteParams.CharLimit < 0) { sb.Append("0"); } else { sb.Append(siteParams.CharLimit.ToString()); } // Now that we've built our string, use the QRCodeWriter from ZXing to // build the QR Code image and assign the bitmap to the picture box: byteMatrix = qrCodeWriter.encode(sb.ToString(), BarcodeFormat.QR_CODE, 200, 200); pictureBox1.Image = byteMatrix.ToBitmap(); } // If the selection in the combo box wasn't useful, empty the picture box: else { pictureBox1.Image = null; } } // Similarly, if anything blew up, empty the picture box: catch { pictureBox1.Image = null; } }
/// <summary> /// Export a list of <see cref="SiteParameters"/> to an encrypted export file. Note /// that this method only exports to the newer XML-based cross-platform format, not /// the old platform specific format that is no longer supported. /// </summary> /// <param name="filename">A string containing the full path to the export file</param> /// <param name="password">A string containing the password used to encrypt the /// file</param> /// <param name="generator">A string containing the "generator" ID for the file, usually /// the full application name ("Cryptnos for Windows") and version number. If this /// value is null the generator tag will be omitted from the file.</param> /// <param name="comment">A string containing an optional comment. If this value is /// null the comment tag will be omitted from the file.</param> /// <param name="siteList">A <see cref="List"/> of <see cref="SiteParameters"/> to /// export</param> /// <exception cref="ArgumentException">Thrown if any required field (file name, /// password, or site list) is empty or null</exception> /// <exception cref="Exception">Thrown if anything blows up along the way</exception> public static void ExportToFile(string filename, string password, string generator, string comment, List <SiteParameters> siteList) { try { // A little bit of sanity checking. Make sure our required inputs are // not null or empty: if (String.IsNullOrEmpty(filename)) { throw new ArgumentException("File name is empty or null"); } if (String.IsNullOrEmpty(password)) { throw new ArgumentException("Password is empty or null"); } if (siteList == null || siteList.Count == 0) { throw new ArgumentException("Site parameter list is empty or null"); } // Set up the XML formatting options for our XML writer. I don't think these // guys are actually essential, given that our XML is not meant to be human // readable, but they seemed to work for Mandelbrot Madness! so I'll keep them // here. XmlWriterSettings xws = new XmlWriterSettings(); xws.Indent = true; xws.IndentChars = "\t"; xws.CloseOutput = true; xws.Encoding = Encoding.UTF8; // We won't be writing directly to a file, at least not yet. Create a memory // stream for us to write to initially, then open up the XML writer to point // to that stream. Note that we'll also gzip the XML as it goes into the // memory stream to compress it. MemoryStream ms = new MemoryStream(); XmlWriter xw = XmlWriter.Create(new GZipStream(ms, CompressionMode.Compress), xws); // Start writing out our XML by putting in the required headers. Note that // the <version> tag is required and for now must be 1, but the <generator> // and <comment> tags are technically optional. Generator is highly recommended, // however, as that helps us ID where the file came from. xw.WriteStartDocument(); xw.WriteStartElement("cryptnos", "http://www.cryptnos.com/"); xw.WriteElementString("version", "1"); if (!String.IsNullOrEmpty(generator)) { xw.WriteElementString("generator", generator); } if (!String.IsNullOrEmpty(comment)) { xw.WriteElementString("comment", comment); } xw.WriteElementString("siteCount", siteList.Count.ToString()); // Start writing out the <sites> tag xw.WriteStartElement("sites"); // Now step through each site parameter group and write out a <site> // tag to contain its data: foreach (SiteParameters site in siteList) { xw.WriteStartElement("site"); xw.WriteElementString("siteToken", site.Site); xw.WriteElementString("hash", HashEngine.HashEnumStringToDisplayHash(site.Hash)); xw.WriteElementString("iterations", site.Iterations.ToString()); xw.WriteElementString("charTypes", site.CharTypes.ToString()); if (site.CharLimit < 0) { xw.WriteElementString("charLimit", "0"); } else { xw.WriteElementString("charLimit", site.CharLimit.ToString()); } xw.WriteEndElement(); } // Close the <sites> tag: xw.WriteEndElement(); // Close the <cryptnos> tag and the rest of the document: xw.WriteEndElement(); xw.WriteEndDocument(); xw.Flush(); xw.Close(); ms.Flush(); ms.Close(); // Get the contents of the memory stream as raw bytes: byte[] plaintext = ms.ToArray(); // Create the cipher. Note that we're using the encryption // mode, and that we're passing in the password: BufferedBlockCipher cipher = CreateCipher(password, true); // Create our ciphertext container. Note that we call the // cipher's getOutputSize() method, which tells us how big // the resulting ciphertext should be. In practice, this // has always been the same size as the plaintext, but we // can't take that for granted. byte[] ciphertext = new byte[cipher.GetOutputSize(plaintext.Length)]; // Do the encyrption. Note that the .NET version is different from // the Java version. Here we've got it easy. The BC classes include // a simpler one-call DoFinal() method that does everything for us. ciphertext = cipher.DoFinal(plaintext); // Write the ciphertext to the export file: FileStream fs = new FileStream(filename, FileMode.Create); fs.Write(ciphertext, 0, ciphertext.Length); // Close up shop: fs.Flush(); fs.Close(); plaintext = null; ciphertext = null; } catch (Exception ex) { throw ex; } }