diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..eba827a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,124 @@
+
+# Created by https://www.gitignore.io/api/macos,swift,xcode
+# Edit at https://www.gitignore.io/?templates=macos,swift,xcode
+
+### macOS ###
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+### Swift ###
+# Xcode
+#
+# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
+
+## Build generated
+build/
+DerivedData/
+
+## Various settings
+*.pbxuser
+!default.pbxuser
+*.mode1v3
+!default.mode1v3
+*.mode2v3
+!default.mode2v3
+*.perspectivev3
+!default.perspectivev3
+xcuserdata/
+
+## Other
+*.moved-aside
+*.xccheckout
+*.xcscmblueprint
+
+## Obj-C/Swift specific
+*.hmap
+*.ipa
+*.dSYM.zip
+*.dSYM
+
+## Playgrounds
+timeline.xctimeline
+playground.xcworkspace
+
+# Swift Package Manager
+# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
+# Packages/
+# Package.pins
+# Package.resolved
+.build/
+
+# CocoaPods
+# We recommend against adding the Pods directory to your .gitignore. However
+# you should judge for yourself, the pros and cons are mentioned at:
+# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
+# Pods/
+# Add this line if you want to avoid checking in source code from the Xcode workspace
+# *.xcworkspace
+
+# Carthage
+# Add this line if you want to avoid checking in source code from Carthage dependencies.
+# Carthage/Checkouts
+
+Carthage/Build
+
+# fastlane
+# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
+# screenshots whenever they are needed.
+# For more information about the recommended setup visit:
+# https://docs.fastlane.tools/best-practices/source-control/#source-control
+
+fastlane/report.xml
+fastlane/Preview.html
+fastlane/screenshots/**/*.png
+fastlane/test_output
+
+# Code Injection
+# After new code Injection tools there's a generated folder /iOSInjectionProject
+# https://github.com/johnno1962/injectionforxcode
+
+iOSInjectionProject/
+
+### Xcode ###
+# Xcode
+# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
+
+## User settings
+
+## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
+
+## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
+
+### Xcode Patch ###
+*.xcodeproj/*
+!*.xcodeproj/project.pbxproj
+!*.xcodeproj/xcshareddata/
+!*.xcworkspace/contents.xcworkspacedata
+/*.gcno
+**/xcshareddata/WorkspaceSettings.xcsettings
+
+# End of https://www.gitignore.io/api/macos,swift,xcode
diff --git a/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Manifest.plist b/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Manifest.plist
new file mode 100644
index 0000000..7fc42a4
--- /dev/null
+++ b/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Manifest.plist
@@ -0,0 +1,16 @@
+
+
+
+
+ Name
+ Chapter 1
+ Pages
+
+ Introduction.cutscenepage
+ Cryptography Foundation.playgroundpage
+ Symmetric-Key Cryptography.playgroundpage
+ Asymmetric-Key Cryptography.playgroundpage
+ Practice.playgroundpage
+
+
+
diff --git a/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Asymmetric-Key Cryptography.playgroundpage/Contents.swift b/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Asymmetric-Key Cryptography.playgroundpage/Contents.swift
new file mode 100644
index 0000000..eec7086
--- /dev/null
+++ b/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Asymmetric-Key Cryptography.playgroundpage/Contents.swift
@@ -0,0 +1,80 @@
+//#-hidden-code
+//
+// See LICENSE folder for this template’s licensing information.
+//
+// Abstract:
+// The Swift file containing the source code edited by the user of this playground book.
+//
+
+import Foundation
+import PlaygroundSupport
+//#-end-hidden-code
+/*:
+# Asymmetric-Key Cryptography
+In asymmetric-key cryptography, we use a key-pair which contains a public key and a private key. After generating a key-pair, we usually send the public one to others, and keep the private one on the disk. As a result, anyone holding your public key can use it to send encrypted messages to you, and it can only be decrypted using the corresponding private key.
+
+This is to say, the sender doesn't need to know how to decrypt the content when encrypting, which solves the key distribution problem.
+
+> Use `generateKeyPair()` to generate a key-pair (this may take a while)
+>
+> Use `encrypt(contentData: , usingPublicKey: )` and `decrypt(contentData: , usingPrivateKey: )` to encrypt/decrypt
+>
+> For detailed usage, see help of each function
+
+- Example:
+```
+let keyPair = generateKeyPair()
+let text = "TOP SECRET"
+let textData = text.data(using: .utf8)!
+let encrypted = encrypt(contentData: textData, usingPublicKey: keyPair.publicKey)
+let decrypted = decrypt(contentData: encrypted, usingPrivateKey: keyPair.privateKey)
+print(String(data: decrypted, encoding: .utf8)!)
+// Output: "TOP SECRET"
+```
+
+- Important:
+Encrypting/Decrypting using asymmetric-key cryptography can be **way slower** than symmetric-key cryptography, and therefore is **not suitable for large files**.
+*/
+
+// Encrypt the text using a designated public key
+func encrypt(text: String, usingPublicKey publicKey: SecKey) -> Data {
+ let textData = text.data(using: .utf8)!
+ return encrypt(contentData: /*#-editable-code*/<#T##Plain Data##Data#>/*#-end-editable-code*/
+ , usingPublicKey: /*#-editable-code*/<#T##Public Key##SecKey#>/*#-end-editable-code*/
+ )
+}
+
+// Decrypt the text using a designated private key
+func decrypt(encryptedData: Data, usingPrivateKey privateKey: SecKey) -> String {
+ let decrypted = decrypt(contentData: /*#-editable-code*/<#T##Encrypted Data##Data#>/*#-end-editable-code*/, usingPrivateKey: /*#-editable-code*/<#T##Private Key##SecKey#>/*#-end-editable-code*/)
+ return String(data: decrypted, encoding: .utf8)!
+}
+
+//#-hidden-code
+let keyPair = generateKeyPair()
+let randomContent = generateRandomContent()
+let encrypted = encrypt(text: randomContent, usingPublicKey: keyPair.publicKey)
+let decrypted = decrypt(encryptedData: encrypted, usingPrivateKey: keyPair.privateKey)
+if decrypted == randomContent {
+ PlaygroundPage.current.assessmentStatus = .pass(message: """
+Congratulations, You've learnt how to use asymmetric-key cryptography!
+
+[Cryptography & Privacy in Practice: Secure Chat](@next)
+""")
+} else {
+ PlaygroundPage.current.assessmentStatus = .fail(hints: ["Please read the text above again to ensure you understand how to use asymmetric cryptography."], solution: """
+```
+func encrypt(text: String, usingPublicKey publicKey: SecKey) -> Data {
+ let textData = text.data(using: .utf8)!
+ return encrypt(contentData: textData, usingPublicKey: publicKey)
+}
+
+func decrypt(encryptedData: Data, usingPrivateKey privateKey: SecKey) -> String {
+ let decrypted = decrypt(contentData: encryptedData, usingPrivateKey: privateKey)
+ return String(data: decrypted, encoding: .utf8)!
+}
+```
+""")
+
+}
+//#-end-hidden-code
diff --git a/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Asymmetric-Key Cryptography.playgroundpage/LiveView.swift b/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Asymmetric-Key Cryptography.playgroundpage/LiveView.swift
new file mode 100644
index 0000000..d614003
--- /dev/null
+++ b/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Asymmetric-Key Cryptography.playgroundpage/LiveView.swift
@@ -0,0 +1,12 @@
+//
+// See LICENSE folder for this template’s licensing information.
+//
+// Abstract:
+// Instantiates a live view and passes it to the PlaygroundSupport framework.
+//
+
+import UIKit
+import PlaygroundSupport
+
+// Instantiate a new instance of the live view from the book's auxiliary sources and pass it to PlaygroundSupport.
+PlaygroundPage.current.liveView = instantiateLiveView()
diff --git a/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Asymmetric-Key Cryptography.playgroundpage/Manifest.plist b/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Asymmetric-Key Cryptography.playgroundpage/Manifest.plist
new file mode 100644
index 0000000..ffac2ee
--- /dev/null
+++ b/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Asymmetric-Key Cryptography.playgroundpage/Manifest.plist
@@ -0,0 +1,12 @@
+
+
+
+
+ Name
+ Asymmetric-Key Cryptography
+ LiveViewEdgeToEdge
+
+ LiveViewMode
+ VisibleByDefault
+
+
diff --git a/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Cryptography Foundation.playgroundpage/Contents.swift b/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Cryptography Foundation.playgroundpage/Contents.swift
new file mode 100644
index 0000000..1110191
--- /dev/null
+++ b/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Cryptography Foundation.playgroundpage/Contents.swift
@@ -0,0 +1,27 @@
+//#-hidden-code
+//
+// See LICENSE folder for this template’s licensing information.
+//
+// Abstract:
+// The Swift file containing the source code edited by the user of this playground book.
+//
+//#-end-hidden-code
+/*:
+# Cryptography Foundation
+## What's Cryptography?
+In software development, we use cryptography to do a lot of things that are related to security, for example, encrypting and decrypting.
+## What Will We Learn
+In this playground book, we'll learn two of the most basic cryptography concepts so that you can secure the app:
+### Symmetric-Key Cryptography
+In symmetric-key cryptography, we use a key (just a password) which is shared between the sender and the receiver. Anyone holding the key can decrypt the content.
+### Asymmetric-Key Cryptography
+By contrast, in asymmetric-key cryptography, we use key-pairs. A key-pair is made up of a public key and a private key. After generating a key-pair, we keep the private one on our disk and share the public one to others. Anyone can encrypt a message using the public key, and only the holder of the corresponding private key can decrypt it.
+
+> A bit confused, or TL;DR? Don't be afraid! You'll understand how to use them in the following part with ease.
+
+[Let's Go!](@next)
+*/
+//#-hidden-code
+import PlaygroundSupport
+PlaygroundPage.current.assessmentStatus = .pass(message: "[Let's go!](@next)")
+//#-end-hidden-code
diff --git a/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Cryptography Foundation.playgroundpage/LiveView.swift b/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Cryptography Foundation.playgroundpage/LiveView.swift
new file mode 100644
index 0000000..d614003
--- /dev/null
+++ b/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Cryptography Foundation.playgroundpage/LiveView.swift
@@ -0,0 +1,12 @@
+//
+// See LICENSE folder for this template’s licensing information.
+//
+// Abstract:
+// Instantiates a live view and passes it to the PlaygroundSupport framework.
+//
+
+import UIKit
+import PlaygroundSupport
+
+// Instantiate a new instance of the live view from the book's auxiliary sources and pass it to PlaygroundSupport.
+PlaygroundPage.current.liveView = instantiateLiveView()
diff --git a/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Cryptography Foundation.playgroundpage/Manifest.plist b/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Cryptography Foundation.playgroundpage/Manifest.plist
new file mode 100644
index 0000000..54396f4
--- /dev/null
+++ b/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Cryptography Foundation.playgroundpage/Manifest.plist
@@ -0,0 +1,12 @@
+
+
+
+
+ Name
+ Cryptography Foundation
+ LiveViewEdgeToEdge
+
+ LiveViewMode
+ VisibleByDefault
+
+
diff --git a/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Introduction.cutscenepage/Manifest.plist b/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Introduction.cutscenepage/Manifest.plist
new file mode 100644
index 0000000..b415e98
--- /dev/null
+++ b/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Introduction.cutscenepage/Manifest.plist
@@ -0,0 +1,10 @@
+
+
+
+
+ CutsceneReference
+ WWDC19 Cutscene1.html
+ Name
+ Introduction
+
+
diff --git a/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Introduction.cutscenepage/PrivateResources/WWDC19 Cutscene1.html b/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Introduction.cutscenepage/PrivateResources/WWDC19 Cutscene1.html
new file mode 100644
index 0000000..f1b21fd
--- /dev/null
+++ b/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Introduction.cutscenepage/PrivateResources/WWDC19 Cutscene1.html
@@ -0,0 +1,32 @@
+
+
+
+
+
+ WWDC19 Cutscene1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Introduction.cutscenepage/PrivateResources/WWDC19 Cutscene1.hyperesources/D367C0-restorable.plist b/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Introduction.cutscenepage/PrivateResources/WWDC19 Cutscene1.hyperesources/D367C0-restorable.plist
new file mode 100644
index 0000000..098302d
Binary files /dev/null and b/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Introduction.cutscenepage/PrivateResources/WWDC19 Cutscene1.hyperesources/D367C0-restorable.plist differ
diff --git a/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Introduction.cutscenepage/PrivateResources/WWDC19 Cutscene1.hyperesources/HYPE-596.full.min.js b/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Introduction.cutscenepage/PrivateResources/WWDC19 Cutscene1.hyperesources/HYPE-596.full.min.js
new file mode 100644
index 0000000..5ff83f0
--- /dev/null
+++ b/Cryptography & Privacy.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Introduction.cutscenepage/PrivateResources/WWDC19 Cutscene1.hyperesources/HYPE-596.full.min.js
@@ -0,0 +1,185 @@
+(function(){var aa=void 0,h=!0,j=null,l=!1,ba=encodeURIComponent,p=window,ga=Object,ha=Infinity,t=document,u=Math,ka=Number,la=navigator,ma=parseInt,na=parseFloat;function oa(V,E){return V.width=E}function pa(V,E){return V.innerHTML=E}function qa(V,E){return V.speed=E}function sa(V,E){return V.left=E}function ta(V,E){return V.loop=E}function va(V,E){return V.play=E}function wa(V,E){return V.zIndex=E}function xa(V,E){return V.length=E}function ya(V,E){return V.position=E}
+function za(V,E){return V.className=E}function Aa(V,E){return V.pause=E}function Ba(V,E){return V.MozPerspective=E}function Ca(V,E){return V.backgroundImage=E}function Da(V,E){return V.display=E}function Fa(V,E){return V.height=E}
+var Ja="appendChild",H="push",Ka="direction",La="lastPosition",Oa="clearTimeout",Pa="width",Va="round",Wa="slice",Xa="replace",Ya="toFixed",Za="timestamp",$a="ceil",ab="floor",bb="getElementById",cb="offsetWidth",hb="concat",ib="list",jb="extend",kb="charAt",lb="preventDefault",sb="region",tb="button",ub="indexOf",vb="speed",wb="embeds",xb="MAX_VALUE",yb="opera",zb="createElement",Ab="atan2",Bb="identifier",Cb="sqrt",Fb="addEventListener",Gb="setAttribute",Hb="play",Ib="parentElement",Jb="type",Kb=
+"translate",Lb="clear",Qb="childNodes",Rb="Play",Sb="attachEvent",Tb="source",Ub="changedTouches",Vb="zIndex",fc="keys",gc="getElementsByTagName",hc="MIN_VALUE",ic="clientX",jc="clientY",kc="toString",J="length",K="position",lc="create",mc="className",nc="index",oc="clientWidth",vc="setTimeout",wc="removeEventListener",xc="ctrlKey",yc="split",zc="duration",Ac="userAgent",Bc="location",Cc="rotate",Dc="hasOwnProperty",Ec="touches",N="style",Fc="pause",Gc="body",Hc="ownerDocument",Ic="removeChild",Jc=
+"search",Kc="group",Lc="options",Mc="start",Nc="getAttribute",Yc="detachEvent",Zc="clientHeight",$c="contains",ad="element",bd="startTime",cd="removeAttribute",dd="parentNode",ed="update",fd="display",gd="height",hd="splice",id="event",Q="",jd="\n",kd=" ",ld=" -webkit-gradient(linear,left top,left bottom,from(transparent),color-stop(",md=" : ",nd=" rotate(",od=" rotateX(",pd=" rotateY(",qd=" scaleX(",rd=" scaleY(",sd=" translateX(",td=" translateY(",ud=" translateZ(",vd="#",wd="#4ECDC4",xd="#556270",
+yd="#666",Pd="#C44D58",Qd="#C7F464",Rd="#FF6B6B",Sd="#eeeeee",Td="%",Ud="%25",Vd="%27",Wd="%c [Matter] ",Xd="&",Yd=" ",Zd="')",$d="'autoplay='false'class='video'>",ae="'classid='clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B'codebase='http://apple.com/qtactivex/qtplugin.cab'width='",be="'controller='",ce="'enablejavascript='true'postdomevents='true'scale='tofit'name='embedobj_",ze="'height='",Ae="'id='embedobj_",Be="'loop='",Ce="'volume='",De="(",Ee=")",Fe=") ",Ge="*",He=",",Ie=",M12=",Je=
+",M21=",Ke=",M22=",Le=",SizingMethod='auto expand')",Me=",transparent),to(rgba(255,255,255,.5)))",Ne="-1",Oe="-10000",Pe="-2",Qe="-bottom",Re="-moz-",Se="-moz-perspective",Te="-ms-transform",Ue="-ms-transform-origin",Ve="-o-",We="-pie-background",Xe="-webkit-",Ye="-webkit-perspective",Ze="-webkit-tap-highlight-color",$e="-webkit-transform",af=".",bf=".AlphaImageLoader(sizingMethod='scale',src='",cf=".HYPE_element{-webkit-transform:rotateY(0);}video.HYPE_element{-webkit-transform:none;}^{color:#000;`size:16px;`weight:normal;`family:Helvetica,Arial,Sans-Serif;`weight:normal;`style:normal;`variant:normal;text-decoration:none;text-align:left;text-transform:none;text-indent:0;text-shadow:none;line-height:normal;letter-spacing:normal;white-space:normal;word-spacing:normal;@:baseline;border:none;background-color:transparent;background-image:none;-webkit-`smoothing:antialiased;-moz-backface-visibility:hidden;}",
+df=".HYPE_scene ",ef=".Matrix(M11=",ff=".gradient(startColorstr=#00FFFFFF,endColorstr=#00FFFFFF)",gf=".png",hf="/",jf="0",kf="0.0",lf="0123456789ABCDEF",mf="0px",cg="1",dg="1.0",eg="100",fg="100%",gg="50%",hg="600px",ig=": ",jg="",kg="",lg="