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="
",mg="",og='",yd="
",zd="",Ad='