1 of 45

Computer Security

CS 240: Advanced Software Construction

2 of 45

Overview

3 of 45

Computer Security

  • Computer systems should be designed with security in mind
  • Bad actors (hackers) try to compromise systems in many ways
    • Gain unauthorized access to data
      • Data in databases and files (i.e., data “at rest”)
      • Data moving across a network (i.e., data “in motion”)
    • Gain unauthorized access to computers
      • Inject viruses, Launch attacks from someone else’s machines
      • Reconfigure or disable systems, Destroy data
      • Monitor activity
    • Disable a system so it can’t be used
      • DDoS (distributed denial of service) attacks

4 of 45

Computer Security

  • Security is a vast subject. We will provide only a brief introduction.
  • Programmers should learn as much as possible about security and how to build secure systems.
  • We will focus on a few essential topics:
    • Basic concepts and terminology
    • Secure communication using HTTPS
    • Secure password storage
    • Secure data storage

5 of 45

Some Important Security Goals

  • Data Confidentiality
    • Only authorized people and systems can access data
  • Authentication
    • Verifying a person or system’s identity (so you can decide if they can be trusted and/or should be authorized to access your system and data)
  • Data Integrity
    • Verifying that data has not been modified from its original form
  • Non-Repudiation
    • Verifying the origin or authorship of data
    • EXAMPLE: Deciding if data can be trusted
    • EXAMPLE: Preventing crypto-currency users from denying (or repudiating) they performed a crypto transaction

6 of 45

Foundational Concepts

  • There are several concepts and technologies that form the foundation of secure systems.
  • Foundational concepts include:
    • Cryptographic hash functions
    • Data Encryption
      • Symmetric key encryption
      • Asymmetric key encryption
    • Secure key exchange
    • Public key certificates
    • Digital signatures

7 of 45

Cryptographic Hash Functions

8 of 45

Cryptographic (One-Way) Hash Functions

One-Way: Given the Digest (or output),

you cannot recover the Input

Deterministic: Given the same Input, it

Produces the same Digest (or output)

Fixed-Size: The Digest is always the same size (e.g., 160 bits), regardless of the Input size

Pseudo-Random: The output seems statistically random, even though it is not (small change to Input makes the Digest totally different)

9 of 45

Cryptographic Hash Algorithms

  • Historical
    • MD-5 [128-bit digest, designed by Ron Rivest at MIT]
    • SHA-1 [160-bit digest, designed by the National Security Agency]
    • Both of these have been cracked and should no longer be used for applications that require collision resistance (where it must be infeasible to create two inputs that produce the same digest)
    • Sometimes still used for less secure applications
  • Modern
    • SHA-2 supersedes MD-5 and SHA-1
      • SHA-2 is a family of algorithms designed by the National Security Agency
      • SHA-256 is the most popular [256-bit digest]
      • SHA-224, SHA-384, SHA-512, and others are also available
    • SHA-3 is another family of secure hashing algorithms

10 of 45

Hashing data in Java

package demo;��import java.security.MessageDigest;�import java.security.NoSuchAlgorithmException;�import java.nio.charset.StandardCharsets;���public class CryptoHashFunctionDemo {�� public static void main(String[] args) throws NoSuchAlgorithmException {�� String[] allInputs = new String[]{� "Fox",� "Fox",� "The red fox jumps over the blue dog",� "The red fox jumps ouer the blue dog",� };�� for (String input : allInputs) {� // Convert character string to array of bytes� byte[] inputBytes = input.getBytes(StandardCharsets.UTF_8);�� // Calculate message digest� byte[] digestBytes = hashData(inputBytes);�� System.out.println(input);� System.out.println(Utils.bytesToHex(digestBytes));� System.out.println();� }� }�� public static byte[] hashData(byte[] data) throws NoSuchAlgorithmException {� � MessageDigest md = MessageDigest.getInstance("SHA-256");� � byte[] digest = md.digest(data);� � return digest;� }�}��

11 of 45

Cryptographic Hashing Applications

  • SHA-1 digests are used in the algorithm Git uses to calculate commit IDs

  • Verify integrity of files downloaded from the web
    • EXAMPLE: JDK download site

12 of 45

Cryptographic Hashing Applications

  • Anytime you need a compact, unique summary or identifier for some data [extremely likely to be unique, anyway]
  • Anytime you want to ensure that data has not been changed [at rest or in transit]
  • Bitcoin mining algorithm uses SHA-256
  • Secure user password storage and verification [next]
  • Digital signatures [later]

13 of 45

Secure user password storage and verification

  • Many applications store usernames and passwords in a database
  • Applications should not store passwords as “plain text”, because bad actors might gain unauthorized access to the database
  • Instead of storing plain text passwords, store a cryptographic hash of each password
  • When a user logs in, the server hashes the provided password, and compares it to the password hash in the database
    • Not even the server knows a user’s password (just their password hash)

14 of 45

Password hashing

  • Problems with storing password hashes
    • Users that have the same password would have the same password hash values in the database
      • You wouldn’t know their password, but you would know they have the same password
    • Attackers could still crack passwords using a dictionary attack
      • Pre-compute a “dictionary” containing the hashes of all likely passwords (maps hashes to passwords)
      • Discover user passwords by searching the dictionary for the password hashes stored in the database

Password

Password Hash

auhsoJ

39e717cd3f5c4be78d97090c69f4e655

hsifdrowS

f567c40623df407ba980bfad6dff5982

1010NO1Z

711f1f88006a48859616c3a5cbcc0377

sinocarD tupaC

fb74376102a049b9a7c5529784763c53

………..

………..

Database

Dictionary

15 of 45

Password hashing

  • To mitigate password attacks,
    • Add “salt” to passwords
    • Hash passwords using a cryptographic hash function that is expensive to compute

16 of 45

Salted password hashing

  • Salting passwords
    • For each user account, generate a random “salt” value
    • Append user’s salt value to their password before hashing it
    • Store salt and hash(password + salt) in the database
    • Users with the same password no longer have the same password hash value
    • Attackers can no longer use pre-computed password hash dictionaries

17 of 45

Password hash functions

  • Cryptographic hash functions such as SHA-512 are designed to be time and memory-efficient to compute
  • For password hashing, it is best to use a cryptographic hash function that is costly to compute (slow and/or uses lots of memory)
  • When combined with salted passwords, this makes password attacks much more difficult to execute
  • Currently recommended password hashing algorithms include:
    • Argon2
    • scrypt
    • bcrypt

18 of 45

Password hash example - Bcrypt

import org.mindrot.jbcrypt.BCrypt;

public class PasswordExample {

public static void main(String[] args) {

String secret = "toomanysecrets";

String hash = BCrypt.hashpw(secret, BCrypt.gensalt());

// Salt is the first 22 characters after the third $

System.out.println(hash);

String[] passwords = {"cow", "toomanysecrets", "password"};

for (var pw : passwords) {

var match = BCrypt.checkpw(pw, hash) ? "==" : "!=";

System.out.printf("%s %s %s%n", pw, match, secret);

}

}

}

19 of 45

Data Encryption

20 of 45

Encryption / Decryption

  • In Cryptography, Encryption is the process of encoding data so that only authorized parties can read it. Decryption is the process of decoding data back to its original form.
    • Plaintext => the data you are trying to protect
      • “Hello, Alice!”
    • Ciphertext => the data in its encrypted form. “Cipher” is another name for an encryption algorithm
      • “6$8xF9q37^&?”
    • Key => a piece of information (sequence of bits) used as input to a cryptographic algorithm to encode or decode data (often stored in a file)
    • Key Size => The number of bits in the key
      • E.g., 128 bits, 192 bits, 256 bits, 1024 bits, 2048 bits
      • The bigger the key size, the more difficult it will be to crack the encryption

21 of 45

Encryption Algorithms

  • Modern encryption algorithms are divided into two categories

    • “Symmetric Key” (or “Secret Key”) algorithms

    • “Asymmetric Key” (or “Public Key”) algorithms

22 of 45

Symmetric (or Secret) Key Encryption

  • The same key is used for both encryption and decryption
  • Popular Algorithms
    • Historical
      • Data Encryption Standard (DES) [56-bit key]
      • Triple DES (3DES) [three 56-bit keys]
    • Modern
      • Advanced Encryption Standard (AES)
        • 128-bit, 192-bit, or 256-bit key, and
        • 128-bit “initialization vector”
      • Blowfish
        • 32 – 448 bit key
      • Twofish
        • 128-bit, 192-bit, or 256-bit key

23 of 45

Symmetric Key �Encryption in Java

package demo;

import javax.crypto.Cipher;

import javax.crypto.KeyGenerator;

import javax.crypto.SecretKey;

import javax.crypto.spec.IvParameterSpec;

import java.security.SecureRandom;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.InputStream;

import java.io.OutputStream;

public class SymmetricKeyEncryptionDemo {

public static void main(String[] args) throws Exception {

// Create AES key and initialization vector

SecretKey aesKey = createAesKey();

IvParameterSpec aesInitVector = createAesInitVector();

// Encrypt file

try (FileInputStream inputStream = new FileInputStream(args[0]);

FileOutputStream outputStream = new FileOutputStream("encrypted-file")) {

aesEncrypt(inputStream, outputStream, aesKey, aesInitVector);

}

// Decrypt file

try (FileInputStream inputStream = new FileInputStream("encrypted-file");

FileOutputStream outputStream = new FileOutputStream("decrypted-file")) {

aesDecrypt(inputStream, outputStream, aesKey, aesInitVector);

}

}

private static SecretKey createAesKey() throws Exception

{

// Generate a pseudo-random AES encryption key (here we use a 256-bit key)

KeyGenerator keyGen = KeyGenerator.getInstance("AES");

keyGen.init(256);

SecretKey key = keyGen.generateKey();

return key;

}

private static IvParameterSpec createAesInitVector() throws Exception

{

// Generate a pseudo-random AES "initialization vector" (128 bits)

var ivBytes = new byte[16];

new SecureRandom().nextBytes(ivBytes);

return new IvParameterSpec(ivBytes);

}

private static void aesEncrypt(InputStream inputStream, OutputStream outputStream,

SecretKey key, IvParameterSpec initVector) throws Exception {

runAes(Cipher.ENCRYPT_MODE, inputStream, outputStream, key, initVector);

}

private static void aesDecrypt(InputStream inputStream, OutputStream outputStream,

SecretKey key, IvParameterSpec initVector) throws Exception {

runAes(Cipher.DECRYPT_MODE, inputStream, outputStream, key, initVector);

}

private static void runAes(int cipherMode, InputStream inputStream, OutputStream outputStream,

SecretKey key, IvParameterSpec initVector) throws Exception {

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

cipher.init(cipherMode, key, initVector);

byte[] inputBytes = new byte[64];

byte[] outputBytes = null;

int bytesRead;

while ((bytesRead = inputStream.read(inputBytes)) != -1) {

outputBytes = cipher.update(inputBytes, 0, bytesRead);

if (outputBytes != null) {

outputStream.write(outputBytes);

}

}

outputBytes = cipher.doFinal();

if (outputBytes != null) {

outputStream.write(outputBytes);

}

outputStream.flush();

}

}

24 of 45

Asymmetric (or Public ) Key Encryption

  • The encryption key and decryption keys are different
  • The two keys must have a certain mathematical relationship, and so must be generated together (called a “key pair”)
  • Given one of the keys, it is infeasible to calculate the other key

25 of 45

Public Key Encryption

  • You can encrypt with either of the keys, and decrypt with the other key (they reverse each other)
  • Popular Algorithms
    • RSA (invented by Rivest-Shamir-Adleman)
      • 2048-bit and 4096-bit keys are typical
      • Other sizes are possible
    • ECC (Elliptic Curve Cryptography)
      • 192, 224, 256, 384, 448-bit keys, many more
      • Used by Bitcoin algorithms

26 of 45

Public Key Encryption

  • Why is it called “public key” encryption?
  • Typical Usage
    • Generate a key pair
    • Keep one of the keys secret. This is your “private key”
    • Give the other key to anyone who wants to send you data. This is your “public key”. There is no need to keep it secret.
    • When sending you data, the sender encrypts the data with your public key
    • When you receive the data, you decrypt the data with your private key
    • No one other than you can decrypt the data because only you have your private key
    • For this to work, it is very important that you keep your private key secret

27 of 45

Public Key Encryption� in Java

package demo;

import javax.crypto.Cipher;

import java.io.*;

import java.nio.charset.StandardCharsets;

import java.nio.file.Files;

import java.nio.file.Paths;

import java.security.*;

public class PublicKeyEncryptionDemo {

public static void main(String[] args) throws Exception {

// Create and save RSA key pair

KeyPair keyPair = createRsaKeyPair();

PublicKey publicKey = keyPair.getPublic();

PrivateKey privateKey = keyPair.getPrivate();

Files.write(Paths.get("public-key"), publicKey.getEncoded());

Files.write(Paths.get("private-key"), privateKey.getEncoded());

Key encryptionKey = publicKey;

Key decryptionKey = privateKey;

//Key encryptionKey = privateKey;

//Key decryptionKey = publicKey;

final String PLAIN_TEXT = "Four score and seven years ago our fathers brought forth, upon this continent," +

" a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal.";

byte[] plainTextBytes = PLAIN_TEXT.getBytes(StandardCharsets.UTF_8);

ByteArrayInputStream inputStream = null;

ByteArrayOutputStream outputStream = null;

// Encrypt data

inputStream = new ByteArrayInputStream(plainTextBytes);

outputStream = new ByteArrayOutputStream();

rsaEncrypt(inputStream, outputStream, encryptionKey);

byte[] cipherTextBytes = outputStream.toByteArray();

System.out.println(Utils.bytesToHex(cipherTextBytes));

System.out.println();

// Decrypt data

inputStream = new ByteArrayInputStream(cipherTextBytes);

outputStream = new ByteArrayOutputStream();

rsaDecrypt(inputStream, outputStream, decryptionKey);

byte[] decryptedPlainTextBytes = outputStream.toByteArray();

String decryptedPlainText = new String(decryptedPlainTextBytes, StandardCharsets.UTF_8);

System.out.println(decryptedPlainText);

System.out.println();

}

private static KeyPair createRsaKeyPair() throws Exception

{

var keyPairGen = KeyPairGenerator.getInstance("RSA");

keyPairGen.initialize(2048);

KeyPair keyPair = keyPairGen.generateKeyPair();

return keyPair;

}

private static void rsaEncrypt(InputStream inputStream, OutputStream outputStream, Key key) throws Exception {

runRsa(Cipher.ENCRYPT_MODE, inputStream, outputStream, key);

}

private static void rsaDecrypt(InputStream inputStream, OutputStream outputStream, Key key) throws Exception {

runRsa(Cipher.DECRYPT_MODE, inputStream, outputStream, key);

}

private static void runRsa(int cipherMode, InputStream inputStream, OutputStream outputStream,

Key key) throws Exception {

Cipher cipher = Cipher.getInstance("RSA");

cipher.init(cipherMode, key);

byte[] inputBytes = new byte[64];

byte[] outputBytes = null;

int bytesRead;

while ((bytesRead = inputStream.read(inputBytes)) != -1) {

outputBytes = cipher.update(inputBytes, 0, bytesRead);

if (outputBytes != null) {

outputStream.write(outputBytes);

}

}

outputBytes = cipher.doFinal();

if (outputBytes != null) {

outputStream.write(outputBytes);

}

outputStream.flush();

}

}

28 of 45

Public Key Encryption

  • Disadvantages of public key encryption
    • Can only encrypt a small amount of data
      • E.g., RSA can only encrypt data less than the key size (e.g., 2048 bits, 4096 bits, etc.)
    • Much slower than symmetric key encryption (e.g., AES)
      • Symmetric key encryption should be used to encrypt large amounts of data
    • Private keys must be securely stored and never shared with others
  • Why would you ever use public key encryption?
  • It has a number powerful applications, including:
    • Secure Symmetric Key Exchange
    • Digital Signatures
  • Public key cryptography is one of the most important inventions in the history of computing

29 of 45

Encryption Applications

  • Protect data as it traverses a computer network to prevent attackers from reading the data (ie, data “in motion”)
    • HTTPS
  • Protect data that is stored in a database or file (ie, data “at rest”)
    • Application-level encryption
    • Database-level encryption
  • Password Managers

30 of 45

Password Managers

  • Store your many passwords in an encrypted file (eg, AES)
  • Master password (or “passphrase”) is required to access your password file
    • You only have to remember one passphrase instead of N passwords
    • Your master password should be as long and complex as possible (eg, 12-14 chars or more, weird characters, very hard to guess)
  • What encryption key does the Password Manager use to encrypt/decrypt the password file?
    • It converts your master password into a symmetric encryption key using a “key derivation function” (eg, PBKDF2 from RSA Security, Inc.)

31 of 45

Secure Key Exchange

32 of 45

Secure Key Exchange

  • Encryption of large amounts of data should be done using symmetric key encryption
  • But, symmetric key encryption requires “Alice” and “Bob” to both use the same secret key. How do they both agree upon and obtain the secret key?
    • Email?, Text?, Phone Call?, Regular mail? List of secret keys agreed upon in advance?
    • All of these are insecure and/or inconvenient
  • Public key encryption can be used to securely and automatically share secret keys between sender and receiver

33 of 45

Secure Key Exchange

1

Data Receiver (Alice)

Data Sender (Bob)

Alice sends Bob her public key (eg,RSA)

Bob generates a random

symmetric key (eg,AES)

Bob encrypts symmetric

key using Alice’s public key

Bob sends Alice encrypted symmetric key

Alice decrypts encrypted symmetric key using her private key

2

3

4

5

Bob encrypts data using symmetric key

6

Bob sends encrypted data to Alice

7

Alice decrypts encrypted data using symmetric key

8

34 of 45

Secure Key Exchange

  • Real-world key exchange algorithms are a bit more complicated than this, but this is the main idea

35 of 45

Secure Communication using HTTPS

36 of 45

Key Exchange in HTTPS/TLS Handshake

1

Server

Client

Client sends Server a random number (Client Random)

Client sends Server another random number (Pre Master Secret) that is encrypted with Server’s public key

Server decrypts Pre Master Secret using its private key

2

4

5

Both Client and Server use Client Random, Server Random, Pre-Master Secret to generate the same symmetric key (eg, AES)

6

Server sends Client a random number (Server Random)

3

Server sends Client its public key cert (eg,RSA)

Client and Server exchange data encrypted with generated symmetric key

7

37 of 45

HTTPS/TLS Server Authentication

  • On the Web, it’s good to know who you are talking to
  • How can Client verify the identity of Server?
  • “Public Key Certificates”!
    • Also called “Digital Certificates”
  • Certificate file = Public Key + Key Owner’s Identifying Information
    • Organization name, Internet domain (e.g., *.acme.com), Mailing address, Email address, …
  • During the HTTPS/TLS Handshake, Server sends its public key to Client in the form of a Public Key Certificate
  • This gives Client the Server’s public key, as well as Server’s identity

38 of 45

HTTPS/TLS Server Authentication

  • How do we prevent Server from creating a fraudulent Certificate that claims a false identity?
  • Certificate files are created and issued by trusted organizations called “Certificate Authorities” (Let’s Encrypt, GoDaddy, DigiCert, Sectigo, etc.)
  • Certificate authorities digitally sign the certificate files they issue so their authenticity can be verified by anyone (i.e., web browsers)
  • After receiving your certificate file, install the certificate file on your web server so clients will know who you are
  • When you need a Certificate,
    • Generate a public/private key pair
    • Keep your Private Key in a secure place (no one else should have it)
    • Send your Public Key and Identifying Information to a Certificate Authority in a “certificate signing request” (CSR)

39 of 45

HTTPS/TLS Server Authentication

  • Upon receiving your CSR, the Certificate Authority will verify your identity, then create and sign your Certificate file, and send it to you
  • The Certificate Authority’s signature gives clients confidence that the information in the certificate file is trustworthy
  • How does a Certificate Authority digitally sign a Certificate file? [next]

40 of 45

Self-Signed Certificates for Development/Testing

  • Most Certificate Authorities charge money to create certificates
  • Let’s Encrypt is a non-profit that creates 90-day certificates for free
  • Software developers sometimes create “self-signed” certificates for use during development and testing
  • Web browsers do not trust self-signed certificates unless configured to do so
  • There are many tools to create self-signed certificates. OpenSSL is popular.

# Create a 10-year self-signed certificate

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 3650 -nodes \

             -subj "/C=US/ST=Oregon/L=Portland/O=Company Name/OU=Org/CN=www.example.com" 

41 of 45

Digital Signatures

42 of 45

Digital Signatures

  • How can Client know that Server’s Certificate actually came from a trusted Certificate Authority?
  • More generally, how can the creator of a file “sign” the file with a signature that cannot be forged, and that can be verified by anyone who receives a copy of the file?

43 of 45

Creating a Digital Signature

  • Signer runs data through cryptographic hash function (eg, SHA-256) to create “signer digest”
  • Signer encrypts digest using their private key. This is the “digital signature”
  • Signer sends data + digital signature to Receiver

44 of 45

Verifying a Digital Signature

  • Receiver runs data through cryptographic hash function to create “receiver digest”
  • Receiver decrypts digital signature using Signer’s public key to recover “signer digest”
  • Receiver compares “receiver digest” with “signer digest”. If they are equal, the signature is valid. If they are not equal, the signature is invalid

45 of 45

Digital Signature Applications

  • Certificate Authorities digitally sign public key certificate files
  • Crypto-currencies (eg, Bitcoin) use digital signatures to verify the authenticity of transactions (ie, transactions cannot be forged or repudiated)
  • Any kind of message, document, or file could be digitally signed to verify its origin and prevent forgery (finance, healthcare, legal, military, etc.)