Talks

The Art & Craft of Secrets: Using the Cryptographic Toolbox

The Art & Craft of Secrets: Using the Cryptographic Toolbox

by Michael Swieton

In the talk titled "The Art & Craft of Secrets: Using the Cryptographic Toolbox," Michael Swieton discusses the intricacies of cryptographic tools and their significance in establishing trust and ensuring privacy in applications. The session emphasizes that while choosing an encryption algorithm is crucial, effectively integrating various cryptographic components with application frameworks is equally essential to maintaining security. Key points discussed include:

  • The Concept of Trust: Trust is foundational in security; it often stems from a chain of trust that includes users, certificates, authorities, and the environment where transactions occur.
  • Authentication and Identity Verification: Examples illustrate the importance of verifying identity through secure methods like public key infrastructures and the significance of SSL/TLS in maintaining secure channels for authentication.
  • Session Management: The talk explains how user sessions work, emphasizing the need for secure session tokens that can be revoked, highlighting potential vulnerabilities from session hijacking.
  • Password Security: Swieton warns against storing plaintext passwords and discusses the merits of hashing techniques, including complex hashing algorithms like bcrypt that mitigate risks associated with password reuse and data breaches.
  • Single Sign-On Mechanisms: The complexities of implementing single sign-on (SSO) are examined, illustrating how cryptographic operations underlie the trust established between separate systems.
  • Real-World Security Breaches: Anecdotes such as the Firesheep attack are presented to show vulnerabilities when SSL/TLS is not comprehensively applied to all communications within applications.

In conclusion, Swieton urges the use of well-audited cryptographic libraries and emphasizes that security is not solely about selecting an algorithm, but rather about understanding and correctly implementing the entire cryptographic framework within applications to protect user trust.

00:00:13 Thank you for coming, both of you. It looks a lot emptier up here than it did a minute ago, so I'm just going to jump right in. We've got a question to start us off with: do you trust me? Thank you! If you don't, you're in good company. But if you do, I'd like you to take a second and just think about why you trust me. This talk is about why our apps can trust our users and vice versa, so that's the topic of the day.
00:00:38 My name is Michael Swieton, which you know if you read the slide up there. About a year ago, I worked for a company called Atomic Object; this was us, pointing to a screen you can't see. This was us about a year ago, a team of about 50 people, doing custom software development, including web and mobile applications across the board. I have to do the obligatory pitch that I'm sure you'll hear at every single talk today: we are hiring experienced developers at our offices in Ann Arbor and Grand Rapids—hit me up!
00:01:04 Today's talk, however, is not so much about algorithms, bits, and bytes—I'm not going to start unpacking AES, RSA, and padding algorithms and so on. This is a talk about how the different pieces fit together. It turns out that it's a really complicated dance to get all of this working right together, and the material many of us might have experienced in college doesn't cover it adequately. So that's what I want to talk about today. I apologize in advance if some of you wanted more technical details.
00:01:44 In addition to discussing how all of that fits together, we'll also have a story to tell about some real-world security failures to put some context around it. A moment ago, I asked you about trust. You can trust me because I have the ID to prove it. This ID was issued by the government, so I won't go so far as to ask you to trust the government. However, you may need to trust that they checked my birth certificate and other IDs before they issued it. We have my picture on it, and the name matches what you see on the conference program.
00:02:29 You can at least trust that this is the talk that was meant to be given at this slot, even if you don't trust anything else. Almost everything we do in terms of security in our applications is built on a chain of trust like this: something goes from the program to the name, then from the government to the ID. Almost nothing is made from some big overarching solution. It's all tiny little pieces that fit together in just the right way.
00:02:49 In a lot of ways, that terrifies me because it's hard. Here's an example: this is what you get if you run 'rails new' or whatever the command is nowadays and add Devise without applying any styling. I made an example user account for RailsConf, and let's login. Okay, I'm logged in! It's really easy to hand-wave over what just happened when it's buried under a single click. We actually went through many steps: we had to establish a connection, send data, evaluate it, and change things. Let me unpack that.
00:03:22 We lost about a tenth of an inch of screen space, so we had to do a DNS lookup to find the server. We had to make a connection and somehow magically make it secure so we can send our credentials, check them, and log the person in. That’s great, and it's better than what we had, but it's still pretty hand-wavy. Before we do anything else, we're going to check the server certificate for authenticity.
00:04:34 Authentication is important. Here's an example: back in 2008, a man stole roughly $850,000 from two banks around the DC area. He walked in and said, 'Hey, I'm here for the pickup,' and he looked right—he had the uniform, the gun, everything, except he wasn't actually working for the security company. He grabbed a bag with half a million dollars and walked out. I don't think he had an armored car; he likely got into a Ford Escort and drove away. He did the same thing the next day and took another $350,000 from a different bank.
00:05:29 This example illustrates that it doesn't matter if you have the truck or if it is secure and locked; it doesn't matter if you're sending your data securely to the wrong place. That's what our certificates are for. But let's dig into what a certificate really is. A certificate consists of three key things. Firstly, it's a public key—the public key for the server we are trying to have a conversation with. However, the key itself is just a number. It doesn't tell us anything, and it's entirely possible that the number could be lying.
00:06:41 In the certificate, we add some metadata that states not only is this the number we’re talking about, but it also belongs to this particular name, for example, amazon.com or railsconf.catalog. We trust that the certificate authority has validated that and has issued the certificate. They sign it, applying a cryptographic signature created with the certificate authority’s private key. By doing this, we establish a chain of trust. I trust my web browser; it comes preloaded with public keys for all the certificate authorities, allowing it to check that the certificate is validly signed.
00:07:37 The certificate signed, in full, shows that this key belongs to that name. Because there's a public key, it's a tool we can use to facilitate secure communications with whoever has that private key. However, we haven't proven that part just yet. All we've proven is that this is the right public key for us to be using. We trust the key based on a system where a certificate authority vouches for it, which is kind of like what the Mafia does to induct a new member.
00:08:42 So now we have the certificate stored in memory, and we’ll use it in just a minute. The next thing we need to do is key exchange. We have a key in that certificate, but that's not what we use to communicate. Generally speaking, public key algorithms like RSA are computationally intensive and have limitations on the size of things you can encrypt. It works well for exchanging a 256-bit key but less well for downloading Season 2 of The Sopranos.
00:09:31 There are two ways of doing key exchange. The first is RSA key exchange: the client generates a secret and encrypts it using the public key in the certificate. Then we can send it over, knowing that no observer will be able to steal the key. The server has that key, and now we have the same key on both sides, enabling secure communication.
00:10:32 Another way we perform key exchange is using Diffie-Hellman. I won’t go into the specifics, but here's a super quick demo. Each side generates a secret and keeps it confidential. We also generate something to exchange publicly, and here’s where we use a server-side signature. This is an extension of regular Diffie-Hellman key exchange that we use with TLS.
00:11:01 Using this method allows us to prove the server's authenticity. If we did RSA, only the server could decrypt the initial message since that’s not applicable here. We need to do that some other way. So, the server signs the key we swap. This means we can construct a session key from it. Here’s the cool part: the first half of our generated secret never gets transmitted. This provides a facility we call forward secrecy.
00:12:04 If you remember what I showed you about RSA, all the data that matters is sent over the connection. So, if someone recorded that data, even if they didn’t have the private key at the time, if they acquire it later, they can go back and decrypt it. With Diffie-Hellman, as long as we delete untransmitted parts, it’s unlikely anyone will reproduce that particular conversation.
00:12:47 Now, it’s interesting to note that forward secrecy is actually not enabled by default in most of the cipher suites that SSL and TLS provide. It was a significant news item when Google enabled it for all their services, so it's worth considering. At this point, we've established session keys, and we can start encrypting.
00:13:18 Let’s review what we’ve accomplished: we talked about authenticity, which ensures we’re communicating with the correct person. Privacy is also apparent; I don't want anyone observing my data. The last component is integrity, but I didn't talk much about that. The way we ensure integrity with TLS is that every time we exchange data, a hash is provided alongside it.
00:14:01 This means that on the receiving end, they can validate that the hash still holds, making it a thread through everything we've discussed. These are components we typically don't deal with directly in our daily work, but the actual login mechanics are what tools like Devise give us. Through Devise, your login controller will manage these components for you.
00:14:50 All these components relate to the transport layer. You can think of it in this way: at the top are components someone smarter than I wrote and put in Apache or Nginx. In our browser, such as Chrome or Safari, we'll have our own applications—JavaScript, HTML, gem file, controllers. The responsibility lies with us regarding that code.
00:15:38 I'll now focus on how our apps handle data internally. I started a development server and am going to make some requests. Let me show you the login request we demoed earlier. Since this is in development mode, I don’t have TLS enabled, which means I can directly telnet in and see what's happening behind the scenes when I do this.
00:16:44 Since there are no layers between us, when I click the login button, it makes a post request to the users controller to sign in. At the bottom, you see the data: I'm sending my email and password in a URL-encoded format, relying on it being sent over an encrypted channel. If it weren't, this is exactly what an observer would see.
00:17:31 Now, verifying that login can take some work. This is the server log output, and the key part is that I sent a username of [email protected]. So, I'll dig through my users database to find that record. Interestingly, that's the only piece of the login process that shows up in our logs, while most of the verification happens in memory.
00:18:10 I want to dwell on passwords for a moment since they're something we deal with often, and it’s easy for us to screw up. Passwords come from users, and we can't revoke those without irritating them. Let's say we have some users: some have strong passwords, some have duplicates, and some have weak passwords.
00:18:46 Storing plaintext passwords is tempting because it's easy, but it’s a terrible idea. If someone gains access to our database, they have all our users’ passwords. Due to password reuse, if our database leaks—which happens frequently in the news—we're exposing not just our users’ passwords but likely their bank account credentials as well.
00:19:50 Thus, we shouldn't store passwords in plaintext. So, say you have a password, which results in data looking like this in the database. We take the hash of whatever the user provides and compare it against what’s stored. However, this method still leaves us vulnerable to duplicate passwords. Also, keep in mind that SHA-1 is incredibly fast.
00:20:48 In 2013, at the Four Seasons Hotel in New York, a massive amount of jewelry was stolen. The thieves walked in during the daylight, smashed the jewelry case with a sledgehammer, and left with millions of dollars worth of goods before anyone could react. This incident is an excellent example of unexpected failure modes.
00:21:52 This serves as a metaphor for password hashes. While it seems infeasible to guess, there’s an attack type called rainbow tables, which uses a time-space trade-off to create lookup tables for passwords. These lookup tables can be massive but are readily accessible. Just earlier this year, we saw reports of major breaches implying that even with seeming security, many organizations are vulnerable.
00:22:38 However, we can mitigate these risks by applying a salt when storing passwords. In our database, we generate random data that we concatenate with the user's password before hashing. This approach increases our security, making it considerably harder for someone to use rainbow tables against us.
00:23:45 While this method gets us closer to effective security, it still comes with risks since SHA-1 is outdated. In fact, Google recently published attacks targeting SHA-256; it’s a constant battle for security. So, this method is good but not perfect. The best practice is to apply a password hashing algorithm like bcrypt or PBKDF2.
00:24:43 To wrap up the verification process, here's what's stored in the database. The first field denotes the version—in this case, bcrypt version 2. The second field differentiates the password with its work factor, which allows us to scale how difficult the hashing process is. Importantly, we want our password hash to take time because login speed is less critical.
00:25:22 Next, when we hash the user's password, we include the salt and what they provided before checking against what we stored. This sequence culminates in an adequate way to ensure security for login credentials. Now, after capturing my user request, let's examine the server's response.
00:26:07 The critical part from the server's response is the session cookie. In my case, I configured Rails to use a database for session stores, so it may look different for you. The essential takeaway here is that it’s a unique token given to the user, which they can reuse next time.
00:26:50 This token is revocable; if we need to change things, we can simply log the user out—a task more challenging to perform with their actual password. When the user brings that token back in the next request, they will be logged in, completing a process that took us about 22 minutes to detail.
00:27:34 What we've accomplished through this process is that we authenticated the user using their email and password, issued them a unique and unpredictable session token that we can revoke. During the entire process, we guarantee that no one else has that token because it's been exchanged over a secure channel.
00:28:16 Now, consider an incident that occurred during the 2015 Melbourne Cup in Australia. A woman won $800 and excitedly posted about it on Instagram and Facebook. By the time she got to the betting counter, someone had pulled their secret token from that barcode and claimed the prize—this shows the importance of treating your tokens securely.
00:29:09 Not long ago, in 2010, a developer named Eric Butler released a plugin called Firesheep. This particular plugin exposed a vulnerability: major web applications were using SSL to protect the login pages but not the remaining parts of the applications. That means if you were connected to an open Wi-Fi network, your session tokens could be easily intercepted.
00:30:06 The lesson here is that you should always be utilizing Transport Layer Security (TLS) whenever you care about security. Later, when I tested Twitter to see if I could perform the same session hijacking attack, I accessed my Twitter account and observed the authentication token. Using this token, I could impersonate another user.
00:31:06 However, this does not imply that Twitter is insecure; they did everything right with HTTPS and securing their tokens. My success at accessing other accounts was due to controlling my endpoint—the laptop and browser.
00:32:01 Now, I want to shift gears and talk about single sign-on (SSO). My colleagues at work make fun of me for liking it, but I think it demonstrates well what we’ve discussed. SSO ties together two separate, isolated applications into a shared session, establishing trust with each individual system and between systems.
00:32:55 Let's imagine a simple HR system that knows who I am and an application that houses data of interest—like a wiki. The HR app can authenticate me, but it doesn't have any data of interest. When I go to the wiki to get data without being logged in, it redirects my request to the HR app.
00:33:54 After logging in at the HR app, I get a session cookie, but that cookie is only valid within that app. Therefore, I also receive a token that the wiki app uses to identify me when I attempt to access it. This token must establish my identity and prove that it is authentic.
00:34:40 As I mentioned earlier, the token can include a hashing algorithm for integrity checks, ensuring that the data is trustworthy. The redirect chains my request alongside my identity, and once I follow it, the wiki authenticates me based on that token.
00:35:34 Finally, after following that redirect, I gain access to the data I wanted. My purpose here is to illustrate the complexity of handling SSO and how it ties back to all the discussions we've had, including SSL, tokens, and the secure transfer of data as well as ensuring trust.
00:36:05 Now that we’re coming to a close: I've intentionally kept some of this complex connection at the end to leave you with one thought. This dependency graph of cryptographic primitives and trusted third parties provides a comprehensive perspective on achieving online security. I’m not one to be left trusting random code; instead, I recommend using well-audited third-party libraries for cryptography.
00:36:39 I guess at this point, I want to open the floor for questions, discussions, or comments. Thank you!