{"id":4477,"date":"2018-09-12T18:35:55","date_gmt":"2018-09-12T23:35:55","guid":{"rendered":"http:\/\/neosmart.net\/blog\/?p=4477"},"modified":"2018-09-12T18:36:17","modified_gmt":"2018-09-12T23:36:17","slug":"transparent-encryption-and-decryption-in-rust-with-cryptostreams","status":"publish","type":"post","link":"https:\/\/neosmart.net\/blog\/transparent-encryption-and-decryption-in-rust-with-cryptostreams\/","title":{"rendered":"Transparent encryption and decryption in rust with cryptostreams"},"content":{"rendered":"<p><a href=\"https:\/\/neosmart.net\/blog\/wp-content\/uploads\/rust-logo.png\" rel=\"follow\"><img loading=\"lazy\" decoding=\"async\" class=\"alignright wp-image-4454 colorbox-4477\" src=\"https:\/\/neosmart.net\/blog\/wp-content\/uploads\/rust-logo-600x600.png\" alt=\"\" width=\"121\" height=\"121\" srcset=\"https:\/\/neosmart.net\/blog\/wp-content\/uploads\/rust-logo-600x600.png 600w, https:\/\/neosmart.net\/blog\/wp-content\/uploads\/rust-logo-150x150.png 150w, https:\/\/neosmart.net\/blog\/wp-content\/uploads\/rust-logo-300x300.png 300w, https:\/\/neosmart.net\/blog\/wp-content\/uploads\/rust-logo.png 1024w\" sizes=\"auto, (max-width: 121px) 100vw, 121px\" \/><\/a>C# developers have long been spoiled when it comes to quickly and easily getting up and running with encryption thanks to the <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/system.security.cryptography.cryptostream(v=vs.105).aspx\" rel=\"follow\">.NET <code>CryptoStream<\/code>\u00a0 class<\/a>, which wraps a <code>Stream<\/code>\u00a0instance in a second <code>Stream<\/code>\u00a0that automatically encrypts\/decrypts anything read\/written to\/from it before passing it along to the underlying <code>Stream<\/code>. Long story short, it makes it ridiculously easy to add encryption or decryption facilities to an existing pipeline, as after setting up the <code>CryptoStream<\/code>\u00a0instance you can just treat it like any other <code>Stream<\/code>\u00a0object and read or write to it normally.<\/p>\n<p>Encryption has been somewhat of a sore spot in the rust ecosystem after a few false starts with &#8220;native&#8221; rust encryption libraries that went nowhere, but today the rust community has fortunately adopted the OpenSSL bindings as the approach of choice, and the <a href=\"https:\/\/github.com\/sfackler\/rust-openssl\" rel=\"nofollow\">rust-openssl crate<\/a>\u00a0makes it easy to both bundle and consume the openssl bindings from rust in a cross-platform manner. What it\u00a0<em>doesn&#8217;t<\/em> do is make encryption and decryption any easier than OpenSSL itself does.<\/p>\n<p><!--more--><\/p>\n<p>Enter the <code>cryptostream<\/code>\u00a0crate. Released <a href=\"https:\/\/github.com\/neosmart\/cryptostream\" rel=\"nofollow\">on github<\/a> and <a href=\"https:\/\/crates.io\/crates\/cryptostream\" rel=\"nofollow\">on crates.io<\/a> under the MIT public license, <code>cryptostream<\/code>\u00a0finally provides an easy and transparent way to add encryption and decryption to pipelines involving objects implementing\u00a0<code>Read<\/code>\u00a0or\u00a0<code>Write<\/code>, making encryption (or decryption) as easy as creating a new <code>cryptostream<\/code>\u00a0object, passing in an existing <code>Read<\/code>\/<code>Write<\/code>\u00a0impl, and then reading\/writing from\/to the <code>cryptostream<\/code>\u00a0instead.<\/p>\n<p>Here&#8217;s an example that highlights just how easy it makes the process:<\/p>\n<pre><code class=\"language-rust\">let src: Vec =\r\n\tdecode(\"vuU+0SXFWQLu8vl\/o1WzmPCmf7x\/O6ToGQ162Aq2CHxcnc\/ax\/Q8nTbRlNn0OSPrFuE3yDdOVC35RmwtUIlxKIkWbnxJpRF5yRJvVByQgWX1qLW8DfMjRp7gVaFNv4qr7G65M6hbSx6hGJXvQ6s1GiFwi91q0V17DI79yVrINHCXdBnUOqeLGfJ05Edu+39EQNYn4dky7VdgTP2VYZE7Vw==\").unwrap();\r\nlet key: Vec&lt;_&gt; = decode(\"kjtbxCPw3XPFThb3mKmzfg==\").unwrap();\r\nlet iv: Vec&lt;_&gt; = decode(\"dB0Ej+7zWZWTS5JUCldWMg==\").unwrap();\r\n\r\n\/\/ The source can be any object implementing `Read`. \r\n\/\/ In this case, a simple &amp;[u8] slice.\r\nlet mut decryptor = read::Decryptor::new(src.as_slice(),\r\n\t\t\t\t\t\t\t\t\t\t Cipher::aes_128_cbc(),\r\n\t\t\t\t\t\t\t\t\t\t &amp;key, &amp;iv).unwrap();\r\n\/\/ `decryptor` implements `Read`\r\n\r\nlet mut decrypted = [0u8; 1024]; \/\/ a buffer to decrypt into\r\nlet mut bytes_decrypted = 0;\r\n\r\nloop {\r\n\t\/\/ Just read from the `Decryptor` as if it were\r\n\t\/\/ any other `Read` impl. Decryption is automatic.\r\n\tlet read_count = decryptor.read(&amp;mut decrypted[bytes_decrypted..])\r\n                                  .unwrap();\r\n\tbytes_decrypted += read_count;\r\n\tif read_count == 0 {\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nprintln!(\"{}\", String::from_utf8_lossy(&amp;decrypted));\r\n<\/code><\/pre>\n<p>Cryptography just doesn&#8217;t get any easier than this.<\/p>\n<p>As rust doesn&#8217;t offer a native <code>Stream<\/code>\u00a0type and instead relies on the <code>Read<\/code>\u00a0and <code>Write<\/code>\u00a0traits to provide stream-like functionality, <code>cryptostream<\/code>\u00a0is split into two types, one class acting as a <code>Read<\/code>\u00a0adapter (to &#8220;pull&#8221; encrypted or decrypted bytes from an existing <code>Read<\/code>\u00a0resource), and the other as a <code>Write<\/code>\u00a0adapter (to &#8220;push&#8221; plaintext into an encrypted file or ciphertext into a plaintext file). Furthermore, each of these <code>cryptostream<\/code>\u00a0types is implemented as both a <code>Encryptor<\/code>\u00a0and <code>Decryptor<\/code>\u00a0class, so that it is possible to perform any [read\/write] operation involving on-the-fly [encryption|decryption] of an existing [<code>Read<\/code>|<code>Write<\/code>] resource.<\/p>\n<p><em>This design is inspired by <a href=\"https:\/\/github.com\/alexcrichton\/flate2-rs\" rel=\"nofollow\">the excellent <code>flate2<\/code>\u00a0crate<\/a>, which provides similar on-the-fly transformation of <code>Read<\/code>\/<code>Write<\/code>\u00a0objects for purposes involving compression and decompression.<\/em><\/p>\n<p>So all you have to do is choose one of the four <code>cryptostream<\/code>\u00a0variants:<\/p>\n<ul>\n<li><code>cryptostream::read::Encryptor<\/code><\/li>\n<li><code>cryptostream::read::Decryptor<\/code><\/li>\n<li><code>cryptostream::write::Encryptor<\/code><\/li>\n<li><code>cryptostream::write::Decryptor<\/code><\/li>\n<\/ul>\n<p>When you&#8217;ve chosen the right type, just initialize it with <code>cryptostream::new(&hellip;)<\/code>, passing in the relevant IV, key, and underlying <code>Read<\/code>\u00a0or <code>Write<\/code>\u00a0resource you wish to transparently encrypt\/decrypt to\/from, and then read from or write to it as you would normally.<\/p>\n<p><code>cryptostream<\/code>\u00a0does not yet support any AEAD cipher suites, but support for those will be coming. (If you&#8217;re using a cipher that doesn&#8217;t taken an IV, now would be a\u00a0<em>great<\/em> time to rectify that design decision, but until then, you can pass in <code>None<\/code>\u00a0for the IV and carry on your merry, insecure way.)<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/neosmart\/cryptostream\/\" rel=\"nofollow\">View\/star\/download\/fork on GitHub<\/a><\/li>\n<li><a href=\"https:\/\/docs.rs\/cryptostream\/0.1.0\/cryptostream\/\" rel=\"nofollow\">Documentation on docs.rs<\/a><\/li>\n<li><a href=\"https:\/\/crates.io\/crates\/cryptostream\" rel=\"nofollow\"><code>cryptostream<\/code>\u00a0crate on crates.io<\/a><\/li>\n<\/ul>\n<p>Feedback in the form of comments below or issues and pull requests on GitHub is most welcome.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>C# developers have long been spoiled when it comes to quickly and easily getting up and running with encryption thanks to the .NET CryptoStream\u00a0 class, which wraps a Stream\u00a0instance in a second Stream\u00a0that automatically encrypts\/decrypts anything read\/written to\/from it before &hellip; <a href=\"https:\/\/neosmart.net\/blog\/transparent-encryption-and-decryption-in-rust-with-cryptostreams\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":505,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[975,1],"tags":[989,990,387,11,936,12],"class_list":["post-4477","post","type-post","status-publish","format-standard","hentry","category-security","category-software","tag-crate","tag-crytostream","tag-encryption","tag-programming","tag-rust","tag-security"],"aioseo_notices":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p4xDa-1ad","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/neosmart.net\/blog\/wp-json\/wp\/v2\/posts\/4477","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/neosmart.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/neosmart.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/neosmart.net\/blog\/wp-json\/wp\/v2\/users\/505"}],"replies":[{"embeddable":true,"href":"https:\/\/neosmart.net\/blog\/wp-json\/wp\/v2\/comments?post=4477"}],"version-history":[{"count":8,"href":"https:\/\/neosmart.net\/blog\/wp-json\/wp\/v2\/posts\/4477\/revisions"}],"predecessor-version":[{"id":4485,"href":"https:\/\/neosmart.net\/blog\/wp-json\/wp\/v2\/posts\/4477\/revisions\/4485"}],"wp:attachment":[{"href":"https:\/\/neosmart.net\/blog\/wp-json\/wp\/v2\/media?parent=4477"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/neosmart.net\/blog\/wp-json\/wp\/v2\/categories?post=4477"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/neosmart.net\/blog\/wp-json\/wp\/v2\/tags?post=4477"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}