00:00:19.699
Okay, um, yeah, be kind of brutal with me because this has to go in 30 minutes and there's 180 slides. It's not as bad as it sounds. There are quite a lot of slides that explain a single piece of code, but there’s a lot of code here. Before we start, I’ll make some kind of gesture when it’s time to wrap things up. So, I have you all here under somewhat false pretenses; I never planned this to be a 30-minute talk. I originally intended it to be 45 minutes. Thus, I’ve cut everything that has to do with Sinatra. That’s nothing against Sinatra; it’s just that I’m very rational and logical when I build a slide deck, and I usually start from the bottom of what I’m talking about.
00:01:11.689
Sinatra is the top of what I was going to talk about, so here we are. There’s always a caveat because every bit of code I present can be dangerous. This is partly because it probably doesn’t work as intended and partly because it often involves things most of us don’t know a lot about. So it's very important to provide some disclaimers. I’m worse than a qualified security professional; I’m a next physicist, which means I approach everything involving data with a very strange perspective. Today, we’re going to talk about two main themes: adventure and paranoia, along with the real meaning of paranoia in internet systems.
00:02:05.800
Everything we do on the internet involves trust in some way. We must anchor trust and ensure we know who we're dealing with, and they must be certain they know who they're dealing with as well. When building a web app, we often rely on other people's ideas of how to create this trust and neglect to look under the hood at how things work. One day, this lack of diligence can lead to problems. So today, we’re starting with a brutally low-level, pure Ruby approach to implementing our own security, albeit imperfectly. A simple recipe for securing anything you want is to ensure that you have a well-known presence somewhere—a reliable place where you can assure that people can verify you.
00:03:13.090
You also want to ensure that everyone you interact with has globally unique identifiers. This concept of accepting or establishing credentials means the only person who should truly understand the credentials is you—not the outside world. Storage and transport are generally straightforward, and the separation of authentication and authorization allows for security, meaning if someone breaks one aspect of your security, they don’t necessarily compromise the other aspect. We’ll discuss four key components today, as we won’t have the time to cover everything comprehensively.
00:04:00.700
First, we have globally unique identifiers, and Ruby's standard library includes secure random functionality. It wraps "/dev/urandom" to provide genuine random numbers. When establishing a unique identity, it’s good to start with a random number. The UUID format uses a specific RFC, but you can find all that in the documentation. Secondly, opaque credentials are important because we want to hash data; hashes are one-way functions, which means people cannot revert back to the original data. We only need hashes since we can match on them, but hashes don't reveal the useful secrets someone had initially, ensuring data is kept secure. We'll discuss SHA-512 hashing, which is commonly used in cryptographic applications. SHA-512 has its advantages over bcrypt in some contexts, such as working with banks and government clients.
00:05:07.800
Next, we'll delve into public key cryptography and symmetric ciphers with AES. We'll also touch upon why it’s crucial to use keys only once for each operation; I could provide a demonstration, but I can only do so much today. Finally, we'll think about secure transport, although we won’t have time to deep-dive into it. However, we will discuss HMAC, which stands for hash-based message authentication codes. These codes use hashing to provide even less information than a typical hash, making them very handy for creating secure fingerprints.
00:05:56.490
Ruby is quite adept at cryptography due to its OpenSSL bindings, though it’s known to have its issues. There have certainly been problems in the past, and for instance, I can't get Ruby to build under Snow Leopard because of binding issues with my OpenSSL version. Overall, Ruby is a functional language for encryption purposes. The first example we’ll look at involves generating a random byte stream; I couldn’t exactly think of a useful example that highlights its utility, so this just generates a randomly long string of characters. This form of randomness is useful in various communications.
00:07:01.150
OpenSSL tends to be a love-it or hate-it situation; most people I know, especially those in security, usually dislike it. However, OpenSSL does provide a lot of essential functionality that keeps many in the industry employed. Next, we will discuss the use of cryptographic hashes that are one-way algorithms. You input data, and it returns a more entropic form. This process essentially increases the entropy of the input data, making it sound complicated. I've written wrapper classes for these algorithms because the standard way of using OpenSSL often involves initializing multiple components, and I prefer to create objects that maintain keys and other elements throughout their lifetime.
00:08:02.680
First, you'll need to create an information piece for each model—keeping the digest itself, a salt value for extra entropy, and the number of rounds during hashing to define our workload. We typically do about 100,000 iterations on average. You may find it sounds expensive, but it’s quite cost-effective when you consider the larger picture. The primary aim of this multiple-round hashing approach is to make it more difficult for outsiders trying to crack the hash. In a secure application, you set a specific number of rounds so that every hash in your database has a different complexity, effectively complicating reverse engineering efforts.
00:09:14.300
Next, we'll introduce a signing key which allows us to generate HMAC. In terms of encoding data, we apply simple methods. Each time you get a hex digest, you pass it back in for further processing—though the coding might seem boring, it’s essential for securely signing data. This is an overview of a simple class setup for handling iterative workloads and signing keys. In terms of AES (Advanced Encryption Standard), we often think of it as the type of cryptography we read about in spy novels. Although AES implementations can involve much more intricate modular arithmetic to deter cracking attempts, fundamentally, it’s similar to letter substitution in concept.
00:10:40.200
When wrapping up our discussions on AES, we’ll note that one essential thing is both the actual key and the initialization vector are necessary. When transferring the encrypted data, it's also crucial to pass along the initialization vector. It's considered safe, according to cryptographic standards, to share the initialization vector, while the key should always remain secure. Following this, we’ll discuss a method known as 'update' because we may want to utilize it multiple times under the hood. We won’t delve into the various modes in which AES can be deployed, but CBC (Cipher Block Chaining) is generally popular for its versatility.
00:11:52.020
The Ruby OpenSSL functionality also includes capabilities to generate keys and initialization vectors. The only time you would capture those is when you generate them initially, as there’s no method to query an AES cipher for its key or vector after the fact. Encoding processes are relatively simple; you'll want to reset the cipher whenever needed and ensure you're encrypting correctly. In terms of error handling, if data does not turn into a string, I structure my rescue outcomes to simply respond with a blank value, allowing the process to remain fluid.
00:13:16.760
Next, we’ll tackle the challenge of encrypted fields. To simplify handling encrypted fields, we'll allow searching for records in an encrypted database. This means we wish to set processes to automate encryption during storage and decryption during retrieval, allowing equality checks without requiring explicit decrypting. I'll introduce this concept of fingerprints associated with records: these need to be cryptographically secure to prevent malicious actors from deriving original data just by examining fingerprints. The general process of generating and leveraging an HMAC hash will offer a lightweight method for searching records based on calculated values.
00:14:50.340
Next, we will showcase how to handle our encrypted fields within the model. Each field must have its own symmetric key mapped correctly. Additionally, we need to maintain the key and initialization vector for each, ensuring secure access rights. I’m emphasizing that revealing this information jeopardizes securely stored data. We’ll detail mechanisms for crafting key controls and iterating over those controls to bolster security and simplify automation.
00:15:49.900
We need to devise a straightforward method for verification and validation of equality searches, understanding how to handle these encrypted discoveries. Throughout all of this, we will explore mechanisms built around field excesses: the final goal is to automate, secure, and simplify interactions between fields while maintaining strong encryption. While all of these pieces are necessary, the complexity of coding can still prove daunting. However, successfully getting systems in place will make the process feel overwhelmingly rewarding.
00:17:05.000
In securing the relational models, we’ll tackle structuring identifiers and keys to protect sensitive information. As we wrap up our discussion, I’ll introduce the concept of utilizing federated private data. Take note, it’s prudent to separate your database elements into several compartments—each compartment can exist in different places, each adhering to unique cryptographic standards. This will set up a system in which access remains controlled and thus widely accessible but not compromised, further enhancing data confidentiality. The infrastructure pattern here would ideally lend itself towards simplifying these relationships through RESTful APIs to ensure secure yet efficient transactions.
00:18:54.370
It’s integral we discuss the importance of securing transport, meaning even with a secure database, communicating openly over the internet poses risks. Digital signatures must be effectively implemented to ensure data integrity, and we should encrypt everything that travels across the wire. As much as I would love to dig deep into this theory, time will constrain us; we’ll cover the critical components you need to secure your applications.
00:20:15.500
In closing, I've covered a lot of ground today, and while running over time, I hope you've gained insights that will be useful for your projects. I apologize for rushing through quite a few concepts; there’s more in-depth study necessary on topics like table encryption—where we ideally steer data management away from direct access towards more secure solutions as described earlier. Again, I appreciate you all sticking with me through this data privacy discussion, and I look forward to your questions afterwards.
00:21:32.780
Lastly, if you’re interested in diving into further details or wish to acquire slides for this presentation, I’ll make sure they are available on SlideShare shortly. There’s a wealth of code there worth reviewing for understanding how encryption can fortify your applications. If any conference organizers are present who’d like to engage me for future discussions on this topic, please feel free to reach out! Thank you!