├── .gitignore ├── README.md ├── certificate ├── README.md └── x509 │ ├── ecdsa │ ├── ca.go │ ├── certs │ │ └── .gitkeep │ ├── server.go │ └── verify.go │ └── rsa │ ├── ca.go │ ├── certs │ └── .gitkeep │ ├── server.go │ └── verify.go ├── cipher ├── README.md ├── aead │ └── gcm │ │ └── main.go ├── block │ └── cbc │ │ └── main.go └── stream │ ├── cfb │ └── main.go │ ├── ctr │ └── main.go │ └── ofb │ └── main.go ├── hash ├── README.md ├── md5 │ └── main.go ├── sha-1 │ └── main.go ├── sha-2 │ └── main.go └── sha-3 │ └── main.go ├── https ├── client.go └── server.go ├── mac └── hmac │ └── main.go ├── public-key ├── README.md ├── rsa-oaep │ └── main.go └── rsa-pkcs1v15 │ └── main.go ├── signature ├── dsa │ └── main.go ├── ecdsa │ └── main.go └── rsa │ └── main.go ├── symmetric-key ├── block │ ├── aes │ │ └── main.go │ ├── des │ │ └── main.go │ └── tdes │ │ └── main.go └── stream │ └── rc4 │ └── main.go └── tls ├── README.md ├── client.go └── server.go /.gitignore: -------------------------------------------------------------------------------- 1 | *.pem -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Play with golang [`crypto`](https://golang.org/pkg/crypto/) packages. Each directory contains `main.go`. It's an example usage of that package. You can use it for reference of your code. 2 | 3 | ## References 4 | 5 | - [暗号技術入門 第3版 秘密の国のアリス](http://www.amazon.co.jp/3-ebook/dp/B015643CPE/) 6 | - [https://golang.org/src/crypto/tls/generate_cert.go](https://golang.org/src/crypto/tls/generate_cert.go) 7 | - [Golang : Tutorial on loading GOB and PEM files](https://www.socketloop.com/tutorials/golang-tutorial-on-loading-gob-and-pem-files) 8 | - [Golang : Create x509 certificate, private and public keys](https://www.socketloop.com/tutorials/golang-create-x509-certificate-private-and-public-keys) 9 | - [nareix/tls-example](https://github.com/nareix/tls-example) 10 | -------------------------------------------------------------------------------- /certificate/README.md: -------------------------------------------------------------------------------- 1 | # Certificate 2 | 3 | = Public Key signed by CA (Certification authority) 4 | 5 | ## Why ? 6 | 7 | To reduce, risk of man-in-the-middle attack. 8 | 9 | ## How works ? 10 | 11 | > Alice wants to encrypt message by Bob's public key and send it to bob. Then bob decrypt it by his private key 12 | 13 | 1. CA create pub & priv key 14 | 1. Bob create pub & priv key 15 | 1. Bob register pub key at CA 16 | 1. CA sign Bob's pub key by CA's priv key and create certificate 17 | 1. Alice gets Bob's certificate(pub key) 18 | 1. Alice verifies certificate(pub key) by CA's pub key 19 | 1. Alice encrypts message by Bob's pub key 20 | 1. Alice sends encrypted message to Bob 21 | 1. Bob decrypt message by Bob's priv key 22 | 23 | ## How to veryfy Bob's cert 24 | 25 | How to cert is signed. 26 | 27 | 1. Bob's cert(pub key) is signed by Sapporo CA's priv key 28 | 1. Sapporo CA's cert(pub key) is signed by Hokkaido CA priv key 29 | 1. Hokkaido CA's cert(pub key) is signed by Japan CA(Root CA)'s priv key 30 | 1. Japan CA(Root CA)'s cert(pub key) is signed by self priv key 31 | 32 | How to veryfy Bob's cert signature. 33 | 34 | 1. Alice has Japan CA's cert(pub key) 35 | 1. Alice gets Hokkaido CA's cert(pub key) 36 | 1. Alice verify Hokkaido CA's cert(pub key) signature by Japan CA's pub key 37 | 1. Alice gets Sapporo CA's cert(pub key) 38 | 1. Alice verify Sapporo CA's cert(pub key) signature by Hokkaido CA's pub key 39 | 1. Alice gets Bob's cert(pub key) 40 | 1. Alice verify Bob's cert(pub key) signature by Sapporo CA's pub key 41 | 42 | ## x509 43 | 44 | x509の証明書はASN.1(Abstract Syntax Notation One)で表記される.ASN.1 は情報の抽象構文を定義するが情報のEncodeのフォーマットは限定しない.x509ではDER(Distinguished Encoding Rules)でエンコーディングが行われる.Goでは`encoding/ans1`にDERのエンコーダーが準備されている.またASN.1のlow levelの構造のパーサーが`crypto/x509/pkix`に定義されている.証明書や鍵はPEM(Privacy Enhanced Mail)形式でエンコーディングされてファイルに保存される.これらは`encoding/pem`に定義されている. 45 | 46 | 47 | -------------------------------------------------------------------------------- /certificate/x509/ecdsa/ca.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/ecdsa" 5 | "crypto/elliptic" 6 | "crypto/rand" 7 | "crypto/x509" 8 | "crypto/x509/pkix" 9 | "encoding/pem" 10 | "fmt" 11 | "math/big" 12 | "os" 13 | "time" 14 | ) 15 | 16 | // Generate self-signed certificate Root CA cert (ca.pem) and its key (ca-key.pem) 17 | func main() { 18 | // Generate pub & priv key pair by Elliptic Curve Digital Signature 19 | priv, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader) 20 | if err != nil { 21 | fmt.Printf("Err: %s\n", err) 22 | return 23 | } 24 | 25 | // Create CA certificate template 26 | ca := x509.Certificate{ 27 | IsCA: true, 28 | SerialNumber: big.NewInt(1234), 29 | Subject: pkix.Name{ 30 | Country: []string{"Japan"}, 31 | Organization: []string{"TCNKSM ECDSA CA Inc."}, 32 | }, 33 | 34 | NotBefore: time.Now(), 35 | NotAfter: time.Now().Add(24 * time.Hour), 36 | 37 | KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageCertSign, 38 | ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, 39 | BasicConstraintsValid: true, 40 | } 41 | 42 | // Create Certificate 43 | derBytes, err := x509.CreateCertificate(rand.Reader, &ca, &ca, &priv.PublicKey, priv) 44 | if err != nil { 45 | fmt.Printf("Err: %s\n", err) 46 | return 47 | } 48 | 49 | certOut, err := os.Create("certs/ca.pem") 50 | if err != nil { 51 | fmt.Printf("Err: %s\n", err) 52 | return 53 | } 54 | defer certOut.Close() 55 | 56 | if err := pem.Encode(certOut, &pem.Block{ 57 | Type: "CERTIFICATE", 58 | Bytes: derBytes, 59 | }); err != nil { 60 | fmt.Printf("Err: %s\n", err) 61 | return 62 | } 63 | 64 | keyOut, err := os.OpenFile("certs/ca-key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) 65 | if err != nil { 66 | fmt.Printf("Err: %s\n", err) 67 | return 68 | } 69 | defer keyOut.Close() 70 | 71 | keyBytes, err := x509.MarshalECPrivateKey(priv) 72 | if err != nil { 73 | fmt.Printf("Err: %s\n", err) 74 | return 75 | } 76 | 77 | if err := pem.Encode(keyOut, &pem.Block{ 78 | Type: "EC PRIVATE KEY", 79 | Bytes: keyBytes, 80 | }); err != nil { 81 | fmt.Printf("Err: %s\n", err) 82 | return 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /certificate/x509/ecdsa/certs/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcnksm/go-crypto/b713ca87e6d916c971ab093529037d0605112d2f/certificate/x509/ecdsa/certs/.gitkeep -------------------------------------------------------------------------------- /certificate/x509/ecdsa/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/ecdsa" 5 | "crypto/elliptic" 6 | "crypto/rand" 7 | "crypto/x509" 8 | "crypto/x509/pkix" 9 | "encoding/pem" 10 | "fmt" 11 | "io/ioutil" 12 | "math/big" 13 | "net" 14 | "os" 15 | "time" 16 | ) 17 | 18 | // Generate server cert (server.pem) signed by ca.pem 19 | // and private key (serverkey.pem) 20 | func main() { 21 | // Read CA certificate pem file 22 | caPem, err := ioutil.ReadFile("certs/ca.pem") 23 | if err != nil { 24 | fmt.Printf("Err: %s\n", err) 25 | return 26 | } 27 | caBlock, _ := pem.Decode(caPem) 28 | caCert, err := x509.ParseCertificate(caBlock.Bytes) 29 | if err != nil { 30 | fmt.Printf("Err: %s\n", err) 31 | return 32 | } 33 | 34 | // Read CA private key pem file 35 | caKeyPem, err := ioutil.ReadFile("certs/ca-key.pem") 36 | if err != nil { 37 | fmt.Printf("Err: %s\n", err) 38 | return 39 | } 40 | caKeyBlock, _ := pem.Decode(caKeyPem) 41 | caPriv, err := x509.ParseECPrivateKey(caKeyBlock.Bytes) 42 | if err != nil { 43 | fmt.Printf("Err: %s\n", err) 44 | return 45 | } 46 | 47 | // Generate pub & priv key pair for server certs by Elliptic Curve DSA 48 | priv, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader) 49 | if err != nil { 50 | fmt.Printf("Err: %s\n", err) 51 | return 52 | } 53 | 54 | // Create CA certificate template 55 | cert := x509.Certificate{ 56 | SerialNumber: big.NewInt(12345), 57 | Subject: pkix.Name{ 58 | Country: []string{"Japan"}, 59 | Organization: []string{"TCNKSM WEB ECDSA Inc."}, 60 | }, 61 | 62 | NotBefore: time.Now(), 63 | NotAfter: time.Now().Add(24 * time.Hour), 64 | 65 | IPAddresses: []net.IP{net.ParseIP("127.0.0.1")}, 66 | 67 | KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, 68 | ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, 69 | BasicConstraintsValid: true, 70 | } 71 | 72 | // Create Server Certificate. Sign by CA private key. 73 | derBytes, err := x509.CreateCertificate(rand.Reader, &cert, caCert, &priv.PublicKey, caPriv) 74 | if err != nil { 75 | fmt.Printf("Err: %s\n", err) 76 | return 77 | } 78 | 79 | certOut, err := os.Create("certs/server.pem") 80 | if err != nil { 81 | fmt.Printf("Err: %s\n", err) 82 | return 83 | } 84 | defer certOut.Close() 85 | 86 | if err := pem.Encode(certOut, &pem.Block{ 87 | Type: "CERTIFICATE", 88 | Bytes: derBytes, 89 | }); err != nil { 90 | fmt.Printf("Err: %s\n", err) 91 | return 92 | } 93 | 94 | keyOut, err := os.OpenFile("certs/server-key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) 95 | if err != nil { 96 | fmt.Printf("Err: %s\n", err) 97 | return 98 | } 99 | defer keyOut.Close() 100 | 101 | keyBytes, err := x509.MarshalECPrivateKey(priv) 102 | if err != nil { 103 | fmt.Printf("Err: %s\n", err) 104 | return 105 | } 106 | 107 | if err := pem.Encode(keyOut, &pem.Block{ 108 | Type: "EC PRIVATE KEY", 109 | Bytes: keyBytes, 110 | }); err != nil { 111 | fmt.Printf("Err: %s\n", err) 112 | return 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /certificate/x509/ecdsa/verify.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/x509" 5 | "encoding/pem" 6 | "fmt" 7 | "io/ioutil" 8 | ) 9 | 10 | func main() { 11 | // Read CA certificate 12 | rootPem, err := ioutil.ReadFile("certs/ca.pem") 13 | if err != nil { 14 | fmt.Printf("Err: %s\n", err) 15 | return 16 | } 17 | 18 | roots := x509.NewCertPool() 19 | ok := roots.AppendCertsFromPEM(rootPem) 20 | if !ok { 21 | fmt.Printf("Err: failed to parse root certificate") 22 | return 23 | } 24 | 25 | serverPem, err := ioutil.ReadFile("certs/server.pem") 26 | if err != nil { 27 | fmt.Printf("Err: %s\n", err) 28 | return 29 | } 30 | 31 | serverBlock, _ := pem.Decode(serverPem) 32 | serverCert, err := x509.ParseCertificate(serverBlock.Bytes) 33 | if err != nil { 34 | fmt.Printf("Err: %s\n", err) 35 | return 36 | } 37 | 38 | opts := x509.VerifyOptions{ 39 | Roots: roots, 40 | } 41 | 42 | // Server cert is signed by ca private key. 43 | // Now we can check its sign by ca certs (public key). 44 | if _, err := serverCert.Verify(opts); err != nil { 45 | fmt.Printf("Err: %s\n", err) 46 | return 47 | } 48 | fmt.Printf("Valified!\n") 49 | } 50 | -------------------------------------------------------------------------------- /certificate/x509/rsa/ca.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "crypto/rsa" 6 | "crypto/x509" 7 | "crypto/x509/pkix" 8 | "encoding/pem" 9 | "fmt" 10 | "math/big" 11 | "os" 12 | "time" 13 | ) 14 | 15 | // Generate self-signed certificate Root CA cert (ca.pem) and its key (ca-key.pem) 16 | func main() { 17 | // Generate pub & priv key pair by RSA 18 | size := 2024 19 | priv, err := rsa.GenerateKey(rand.Reader, size) 20 | if err != nil { 21 | fmt.Printf("Err: %s\n", err) 22 | return 23 | } 24 | 25 | // Create CA certificate template 26 | ca := x509.Certificate{ 27 | IsCA: true, 28 | SerialNumber: big.NewInt(1234), 29 | Subject: pkix.Name{ 30 | Country: []string{"Japan"}, 31 | Organization: []string{"TCNKSM CA Inc."}, 32 | }, 33 | 34 | NotBefore: time.Now(), 35 | NotAfter: time.Now().Add(24 * time.Hour), 36 | 37 | KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageCertSign, 38 | ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, 39 | BasicConstraintsValid: true, 40 | } 41 | 42 | // Create Certificate 43 | derBytes, err := x509.CreateCertificate(rand.Reader, &ca, &ca, &priv.PublicKey, priv) 44 | if err != nil { 45 | fmt.Printf("Err: %s\n", err) 46 | return 47 | } 48 | 49 | certOut, err := os.Create("certs/ca.pem") 50 | if err != nil { 51 | fmt.Printf("Err: %s\n", err) 52 | return 53 | } 54 | defer certOut.Close() 55 | 56 | if err := pem.Encode(certOut, &pem.Block{ 57 | Type: "CERTIFICATE", 58 | Bytes: derBytes, 59 | }); err != nil { 60 | fmt.Printf("Err: %s\n", err) 61 | return 62 | } 63 | 64 | keyOut, err := os.OpenFile("certs/ca-key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) 65 | if err != nil { 66 | fmt.Printf("Err: %s\n", err) 67 | return 68 | } 69 | defer keyOut.Close() 70 | 71 | if err := pem.Encode(keyOut, &pem.Block{ 72 | Type: "RSA PRIVATE KEY", 73 | Bytes: x509.MarshalPKCS1PrivateKey(priv), 74 | }); err != nil { 75 | fmt.Printf("Err: %s\n", err) 76 | return 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /certificate/x509/rsa/certs/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcnksm/go-crypto/b713ca87e6d916c971ab093529037d0605112d2f/certificate/x509/rsa/certs/.gitkeep -------------------------------------------------------------------------------- /certificate/x509/rsa/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "crypto/rsa" 6 | "crypto/x509" 7 | "crypto/x509/pkix" 8 | "encoding/pem" 9 | "fmt" 10 | "io/ioutil" 11 | "math/big" 12 | "net" 13 | "os" 14 | "time" 15 | ) 16 | 17 | // Generate server cert (server.pem) signed by ca.pem 18 | // and private key (serverkey.pem) 19 | func main() { 20 | // Read CA certificate pem file 21 | caPem, err := ioutil.ReadFile("certs/ca.pem") 22 | if err != nil { 23 | fmt.Printf("Err: %s\n", err) 24 | return 25 | } 26 | caBlock, _ := pem.Decode(caPem) 27 | caCert, err := x509.ParseCertificate(caBlock.Bytes) 28 | if err != nil { 29 | fmt.Printf("Err: %s\n", err) 30 | return 31 | } 32 | 33 | // Read CA private key pem file 34 | caKeyPem, err := ioutil.ReadFile("certs/ca-key.pem") 35 | if err != nil { 36 | fmt.Printf("Err: %s\n", err) 37 | return 38 | } 39 | caKeyBlock, _ := pem.Decode(caKeyPem) 40 | caPriv, err := x509.ParsePKCS1PrivateKey(caKeyBlock.Bytes) 41 | if err != nil { 42 | fmt.Printf("Err: %s\n", err) 43 | return 44 | } 45 | 46 | // Generate pub & priv key pair for server certs by RSA 47 | size := 2024 48 | priv, err := rsa.GenerateKey(rand.Reader, size) 49 | if err != nil { 50 | fmt.Printf("Err: %s\n", err) 51 | return 52 | } 53 | 54 | // Create CA certificate template 55 | cert := x509.Certificate{ 56 | SerialNumber: big.NewInt(12345), 57 | Subject: pkix.Name{ 58 | Country: []string{"Japan"}, 59 | Organization: []string{"TCNKSM WEB Inc."}, 60 | }, 61 | 62 | NotBefore: time.Now(), 63 | NotAfter: time.Now().Add(24 * time.Hour), 64 | 65 | IPAddresses: []net.IP{net.ParseIP("127.0.0.1")}, 66 | 67 | KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, 68 | ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, 69 | BasicConstraintsValid: true, 70 | } 71 | 72 | // Create Server Certificate. Sign by CA private key. 73 | derBytes, err := x509.CreateCertificate(rand.Reader, &cert, caCert, &priv.PublicKey, caPriv) 74 | if err != nil { 75 | fmt.Printf("Err: %s\n", err) 76 | return 77 | } 78 | 79 | certOut, err := os.Create("certs/server.pem") 80 | if err != nil { 81 | fmt.Printf("Err: %s\n", err) 82 | return 83 | } 84 | defer certOut.Close() 85 | 86 | if err := pem.Encode(certOut, &pem.Block{ 87 | Type: "CERTIFICATE", 88 | Bytes: derBytes, 89 | }); err != nil { 90 | fmt.Printf("Err: %s\n", err) 91 | return 92 | } 93 | 94 | keyOut, err := os.OpenFile("certs/server-key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) 95 | if err != nil { 96 | fmt.Printf("Err: %s\n", err) 97 | return 98 | } 99 | defer keyOut.Close() 100 | 101 | if err := pem.Encode(keyOut, &pem.Block{ 102 | Type: "RSA PRIVATE KEY", 103 | Bytes: x509.MarshalPKCS1PrivateKey(priv), 104 | }); err != nil { 105 | fmt.Printf("Err: %s\n", err) 106 | return 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /certificate/x509/rsa/verify.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/x509" 5 | "encoding/pem" 6 | "fmt" 7 | "io/ioutil" 8 | ) 9 | 10 | func main() { 11 | // Read CA certificate 12 | rootPem, err := ioutil.ReadFile("certs/ca.pem") 13 | if err != nil { 14 | fmt.Printf("Err: %s\n", err) 15 | return 16 | } 17 | 18 | roots := x509.NewCertPool() 19 | ok := roots.AppendCertsFromPEM(rootPem) 20 | if !ok { 21 | fmt.Printf("Err: failed to parse root certificate") 22 | return 23 | } 24 | 25 | serverPem, err := ioutil.ReadFile("certs/server.pem") 26 | if err != nil { 27 | fmt.Printf("Err: %s\n", err) 28 | return 29 | } 30 | 31 | serverBlock, _ := pem.Decode(serverPem) 32 | serverCert, err := x509.ParseCertificate(serverBlock.Bytes) 33 | if err != nil { 34 | fmt.Printf("Err: %s\n", err) 35 | return 36 | } 37 | 38 | opts := x509.VerifyOptions{ 39 | Roots: roots, 40 | } 41 | 42 | // Server cert is signed by ca private key. 43 | // Now we can check its sign by ca certs (public key). 44 | if _, err := serverCert.Verify(opts); err != nil { 45 | fmt.Printf("Err: %s\n", err) 46 | return 47 | } 48 | fmt.Printf("Valified!\n") 49 | } 50 | -------------------------------------------------------------------------------- /cipher/README.md: -------------------------------------------------------------------------------- 1 | # Block Cipher & Stream Cipher 2 | 3 | なぜモードが存在するのか? `DES`や`AES`といったブロック暗号は固定長の長さの平文しか暗号化できない(e.g, `DES`は8byte).任意の長さの平文を暗号化するためにはブロック暗号を繰り返し実行する必要がある.ブロック暗号を繰り返す方法をモードと呼ぶ. 4 | 5 | ## Block Cipher 6 | 7 | ある特定のブロック長で処理を行う暗号アルゴリズム 8 | 9 | - **ECB** (Electronic CodeBook mode): 平文ブロックと暗号文ブロックが一対一の関係になる.したがって平文に同じ値を持つ平文ブロックが複数存在したらそれらの平文ブロックはすべて同じ値の暗号文ブロックに変換されてしまう.攻撃者が暗号化ブロックの順番を入れ替えれば平文の順番も入れ替わってしまう. 10 | - **CBC** (Cipher Block Chainning): 1つ前の暗号ブロックと平文ブロックの`XOR`をとってから暗号化を行う(平文ブロックn `XOR` 暗号ブロックn-1 に暗号アルゴリズムを適用する)ただし一番最初の平文ブロックにはIV(Initialization Vector)と`XOR`をとる.暗号ブロックの一部が欠損すると以後の平文全てに影響が出る.SSL/TLSに利用されている(`3DES_EDE_CBC`,`AES_256_CBC`). 11 | 12 | ## Stream Cipher 13 | 14 | ストリームで順次処理を行う暗号アルゴリズム 15 | 16 | - **CFB** (Cipher FeedBack): 1つ前の暗号ブロックを暗号化したもの(Key Stream)と平文ブロックの`XOR`をとる. 17 | - **OFB** (Output FeedBack): 1つ前の暗号化の出力(Key Stream)を次の暗号化の入力とする.暗号化の出力(Key Stream)と平文で`XOR`をとる(Key Streamを事前につくっておくことができる).もし暗号結果が同じものになったらそれ以後Key Streamは全て同じ値になってしまう.暗号文を1ビット反転させると平文も1ビット反転する 18 | - **CTR** (CounTeR): 1つずつ増加していくカウンタを暗号化して鍵ストリームを作り出す.カウンタを暗号化してKey Streamとする.カウンタは暗号化のたびに異なる値(ノンス)をもとにしてつくる.暗号文を1ビット反転させると平文も1ビット反転する. 19 | 20 | ## AEAD 21 | 22 | Authenticated encryption with associated data. 23 | 24 | - **GCM** (Galois/Counter): *CTR*が暗号文を作り出すと同時に「この暗号文は正しい暗号化によって作られたものである」とう認証子を作り出す.暗号文の偽装を見抜くことができる.TLS1.2で使われる.IVが必要ない 25 | -------------------------------------------------------------------------------- /cipher/aead/gcm/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/cipher" 6 | "crypto/rand" 7 | "fmt" 8 | "io" 9 | ) 10 | 11 | func main() { 12 | plainText := []byte("Bob loves Alice.") 13 | key := []byte("passw0rdpassw0rdpassw0rdpassw0rd") 14 | 15 | // Create new AES cipher block 16 | block, err := aes.NewCipher(key) 17 | if err != nil { 18 | fmt.Printf("err: %s\n", err) 19 | return 20 | } 21 | 22 | aead, err := cipher.NewGCM(block) 23 | if err != nil { 24 | fmt.Printf("err: %s\n", err) 25 | return 26 | } 27 | 28 | fmt.Println(aead.NonceSize()) 29 | nonce := make([]byte, aead.NonceSize()) 30 | if _, err := io.ReadFull(rand.Reader, nonce); err != nil { 31 | fmt.Printf("err: %s\n", err) 32 | return 33 | } 34 | 35 | cipherText := aead.Seal(nil, nonce, plainText, nil) 36 | fmt.Printf("Cipher text: %x\n", cipherText) 37 | 38 | plainText_, err := aead.Open(nil, nonce, cipherText, nil) 39 | if err != nil { 40 | fmt.Printf("err: %s\n", err) 41 | return 42 | } 43 | fmt.Printf("Decrypted text: %s\n", string(plainText_)) 44 | } 45 | -------------------------------------------------------------------------------- /cipher/block/cbc/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/cipher" 6 | "crypto/rand" 7 | "fmt" 8 | "io" 9 | ) 10 | 11 | func main() { 12 | plainText := []byte("Bob loves Alice.") 13 | key := []byte("passw0rdpassw0rdpassw0rdpassw0rd") 14 | 15 | // Create new AES cipher block 16 | block, err := aes.NewCipher(key) 17 | if err != nil { 18 | fmt.Printf("err: %s\n", err) 19 | } 20 | 21 | // The IV (Initialization Vector) need to be unique, but not secure. 22 | // Therefore, it's common to include it at the beginning of the cipher text. 23 | cipherText := make([]byte, aes.BlockSize+len(plainText)) 24 | 25 | // Fill iv with rand value 26 | iv := cipherText[:aes.BlockSize] 27 | if _, err := io.ReadFull(rand.Reader, iv); err != nil { 28 | fmt.Printf("err: %s\n", err) 29 | } 30 | 31 | // Encrypt 32 | encryptMode := cipher.NewCBCEncrypter(block, iv) 33 | encryptMode.CryptBlocks(cipherText[aes.BlockSize:], plainText) 34 | fmt.Printf("Cipher text: %v\n", cipherText) 35 | 36 | // Decrypt 37 | decryptedText := make([]byte, len(cipherText[aes.BlockSize:])) 38 | decryptMode := cipher.NewCBCDecrypter(block, cipherText[:aes.BlockSize]) 39 | decryptMode.CryptBlocks(decryptedText, cipherText[aes.BlockSize:]) 40 | fmt.Printf("Decrypted text: %s\n", string(decryptedText)) 41 | } 42 | -------------------------------------------------------------------------------- /cipher/stream/cfb/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/cipher" 6 | "crypto/rand" 7 | "fmt" 8 | "io" 9 | ) 10 | 11 | func main() { 12 | plainText := []byte("Bob loves Alice.") 13 | key := []byte("passw0rdpassw0rdpassw0rdpassw0rd") 14 | 15 | // Create new DES cipher block 16 | block, err := aes.NewCipher(key) 17 | if err != nil { 18 | fmt.Printf("err: %s\n", err) 19 | } 20 | 21 | // The IV (Initialization Vector) need to be unique, but not secure. 22 | // Therefore, it's common to include it at the beginning of the cipher text. 23 | cipherText := make([]byte, aes.BlockSize+len(plainText)) 24 | 25 | // Create IV 26 | iv := cipherText[:aes.BlockSize] 27 | if _, err := io.ReadFull(rand.Reader, iv); err != nil { 28 | fmt.Printf("err: %s\n", err) 29 | } 30 | 31 | // Encrypt 32 | encryptStream := cipher.NewCFBEncrypter(block, iv) 33 | encryptStream.XORKeyStream(cipherText[aes.BlockSize:], plainText) 34 | fmt.Printf("Cipher text: %v\n", cipherText) 35 | 36 | // Decrpt 37 | decryptedText := make([]byte, len(cipherText[aes.BlockSize:])) 38 | decryptStream := cipher.NewCFBDecrypter(block, cipherText[:aes.BlockSize]) 39 | decryptStream.XORKeyStream(decryptedText, cipherText[aes.BlockSize:]) 40 | fmt.Printf("Decrypted text: %s\n", string(decryptedText)) 41 | } 42 | -------------------------------------------------------------------------------- /cipher/stream/ctr/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/cipher" 6 | "crypto/rand" 7 | "fmt" 8 | "io" 9 | ) 10 | 11 | func main() { 12 | plainText := []byte("Bob loves Alice. But Alice hate Bob...") 13 | key := []byte("passw0rdpassw0rdpassw0rdpassw0rd") 14 | 15 | // Create new AES cipher block 16 | block, err := aes.NewCipher(key) 17 | if err != nil { 18 | fmt.Printf("err: %s\n", err) 19 | } 20 | 21 | // The IV (Initialization Vector) need to be unique, but not secure. 22 | // Therefore, it's common to include it at the beginning of the cipher text. 23 | cipherText := make([]byte, aes.BlockSize+len(plainText)) 24 | 25 | // Create IV 26 | iv := cipherText[:aes.BlockSize] 27 | if _, err := io.ReadFull(rand.Reader, iv); err != nil { 28 | fmt.Printf("err: %s\n", err) 29 | } 30 | 31 | // Encrypt 32 | encryptStream := cipher.NewCTR(block, iv) 33 | encryptStream.XORKeyStream(cipherText[aes.BlockSize:], plainText) 34 | fmt.Printf("Cipher text: %x \n", cipherText) 35 | 36 | // Decrpt 37 | decryptedText := make([]byte, len(cipherText[aes.BlockSize:])) 38 | decryptStream := cipher.NewCTR(block, cipherText[:aes.BlockSize]) 39 | decryptStream.XORKeyStream(decryptedText, cipherText[aes.BlockSize:]) 40 | fmt.Printf("Decrypted text: %s\n", string(decryptedText)) 41 | } 42 | -------------------------------------------------------------------------------- /cipher/stream/ofb/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/cipher" 6 | "crypto/rand" 7 | "fmt" 8 | "io" 9 | ) 10 | 11 | func main() { 12 | plainText := []byte("Bob loves Alice.") 13 | key := []byte("passw0rdpassw0rdpassw0rdpassw0rd") 14 | 15 | // Create new DES cipher block 16 | block, err := aes.NewCipher(key) 17 | if err != nil { 18 | fmt.Printf("err: %s\n", err) 19 | } 20 | 21 | // The IV (Initialization Vector) need to be unique, but not secure. 22 | // Therefore, it's common to include it at the beginning of the cipher text. 23 | cipherText := make([]byte, aes.BlockSize+len(plainText)) 24 | 25 | // Create IV 26 | iv := cipherText[:aes.BlockSize] 27 | if _, err := io.ReadFull(rand.Reader, iv); err != nil { 28 | fmt.Printf("err: %s\n", err) 29 | } 30 | 31 | // Encrypt 32 | encryptStream := cipher.NewOFB(block, iv) 33 | encryptStream.XORKeyStream(cipherText[aes.BlockSize:], plainText) 34 | fmt.Printf("Cipher text: %v \n", cipherText) 35 | 36 | // Decrpt 37 | decryptedText := make([]byte, len(cipherText[aes.BlockSize:])) 38 | decryptStream := cipher.NewOFB(block, cipherText[:aes.BlockSize]) 39 | decryptStream.XORKeyStream(decryptedText, cipherText[aes.BlockSize:]) 40 | fmt.Printf("Decrypted text: %s\n", string(decryptedText)) 41 | } 42 | -------------------------------------------------------------------------------- /hash/README.md: -------------------------------------------------------------------------------- 1 | # Hash functions 2 | 3 | - **MD5**: 128bits 4 | -------------------------------------------------------------------------------- /hash/md5/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/md5" 5 | "fmt" 6 | "io" 7 | ) 8 | 9 | func main() { 10 | 11 | // New hash.Hash computing MD5 checksum. 12 | h := md5.New() 13 | 14 | msg := "Taichi Nakashima" 15 | io.WriteString(h, msg) 16 | checksum := h.Sum(nil) 17 | 18 | fmt.Printf("Length: %d byte\n", len(checksum)) 19 | fmt.Printf("Output: %x\n", checksum) 20 | 21 | fmt.Printf("Output: %x\n", md5.Sum([]byte(msg))) 22 | } 23 | -------------------------------------------------------------------------------- /hash/sha-1/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/sha1" 5 | "fmt" 6 | ) 7 | 8 | func main() { 9 | msg := []byte("Taichi Nakashima") 10 | 11 | checksum1 := sha1.Sum(msg) 12 | fmt.Printf("Length (SHA-1): %d byte (%d bits)\n", len(checksum1), len(checksum1)*8) 13 | fmt.Printf("Output (SHA-1): %x\n\n", checksum1) 14 | } 15 | -------------------------------------------------------------------------------- /hash/sha-2/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/sha256" 5 | "crypto/sha512" 6 | "fmt" 7 | ) 8 | 9 | func main() { 10 | msg := []byte("Taichi Nakashima") 11 | 12 | checksum256 := sha256.Sum256(msg) 13 | fmt.Printf("Length (SHA-256): %d byte (%d bits)\n", len(checksum256), len(checksum256)*8) 14 | fmt.Printf("Output (SHA-256): %x\n\n", checksum256) 15 | 16 | checksum512 := sha512.Sum512(msg) 17 | fmt.Printf("Length (SHA-512): %d byte (%d bits)\n", len(checksum512), len(checksum512)*8) 18 | fmt.Printf("Output (SHA-512): %x\n\n", checksum512) 19 | 20 | checksum512_256 := sha512.Sum512_256(msg) 21 | fmt.Printf("Length (SHA-512/256): %d byte (%d bits)\n", len(checksum512_256), len(checksum512_256)*8) 22 | fmt.Printf("Output (SHA-512/256): %x\n\n", checksum512_256) 23 | } 24 | -------------------------------------------------------------------------------- /hash/sha-3/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "golang.org/x/crypto/sha3" 7 | ) 8 | 9 | func main() { 10 | msg := []byte("Taichi Nakashima") 11 | 12 | // A MAC with 32 bytes of output has 256-bit security strength 13 | h := make([]byte, 64) 14 | 15 | // The SHAKE functions are recommended for most new uses. 16 | // They can produce output of arbitrary length. 17 | // SHAKE256, with an output length of at least 64 bytes, provides 256-bit security against all attacks. 18 | d := sha3.NewShake256() 19 | d.Write(msg) 20 | d.Read(h) 21 | 22 | fmt.Printf("Length: %d byte (%d bits)\n", len(h), len(h)*8) 23 | fmt.Printf("Output: %x\n", h) 24 | } 25 | -------------------------------------------------------------------------------- /https/client.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/tls" 5 | "crypto/x509" 6 | "fmt" 7 | "io/ioutil" 8 | "log" 9 | "net/http" 10 | "path/filepath" 11 | ) 12 | 13 | func main() { 14 | // Read CA certificate 15 | caFile, _ := filepath.Abs("../certificate/x509/ecdsa/certs/ca.pem") 16 | rootPem, err := ioutil.ReadFile(caFile) 17 | if err != nil { 18 | fmt.Printf("Err: %s\n", err) 19 | return 20 | } 21 | 22 | roots := x509.NewCertPool() 23 | if ok := roots.AppendCertsFromPEM(rootPem); !ok { 24 | fmt.Printf("Err: failed to parse root certificate") 25 | return 26 | } 27 | 28 | config := tls.Config{ 29 | RootCAs: roots, 30 | } 31 | 32 | tr := http.Transport{ 33 | TLSClientConfig: &config, 34 | } 35 | 36 | client := http.Client{ 37 | Transport: &tr, 38 | } 39 | 40 | res, err := client.Get("https://127.0.0.1:3000") 41 | if err != nil { 42 | log.Printf("[ERROR] %s", err) 43 | } 44 | defer res.Body.Close() 45 | 46 | buf, err := ioutil.ReadAll(res.Body) 47 | if err != nil { 48 | log.Printf("[ERROR] %s", err) 49 | } 50 | log.Printf("[INFO] response: %q", string(buf)) 51 | } 52 | -------------------------------------------------------------------------------- /https/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | "path/filepath" 7 | ) 8 | 9 | func main() { 10 | certFile, _ := filepath.Abs("../certificate/x509/ecdsa/certs/server.pem") 11 | keyFile, _ := filepath.Abs("../certificate/x509/ecdsa/certs/server-key.pem") 12 | 13 | http.HandleFunc("/", rootHandler) 14 | 15 | port := "3000" 16 | log.Printf("[INFO] Start listen on %s", port) 17 | // http.ListenAndServeTLS calls tls.LoadX509KeyPair(certFile, keyFile) 18 | err := http.ListenAndServeTLS("localhost:"+port, certFile, keyFile, nil) 19 | 20 | if err != nil { 21 | log.Printf("[ERROR] %s", err) 22 | } 23 | } 24 | 25 | func rootHandler(w http.ResponseWriter, r *http.Request) { 26 | log.Printf("[INFO] Request from %s", r.RemoteAddr) 27 | w.Header().Set("Content-type", "text/plain") 28 | w.Write([]byte("Hello with TLS\n")) 29 | } 30 | -------------------------------------------------------------------------------- /mac/hmac/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/hmac" 5 | "fmt" 6 | ) 7 | import "crypto/sha512" 8 | 9 | // hash(opadkey || hash(ipadkey || message)) 10 | // ipadkey = key XOR ipad 11 | // opadkey = key XOR opad 12 | func main() { 13 | msg := []byte("Bob loves Alice.") 14 | key := []byte("passw0rd") 15 | 16 | h1 := hmac.New(sha512.New, key) 17 | h1.Write(msg) 18 | mac1 := h1.Sum(nil) 19 | fmt.Printf("MAC1: %x\n", mac1) 20 | 21 | h2 := hmac.New(sha512.New, key) 22 | h2.Write(msg) 23 | mac2 := h2.Sum(nil) 24 | fmt.Printf("MAC2: %x\n", mac2) 25 | 26 | fmt.Printf("Valid? %v\n", hmac.Equal(mac1, mac2)) 27 | } 28 | -------------------------------------------------------------------------------- /public-key/README.md: -------------------------------------------------------------------------------- 1 | # RSA 2 | 3 | RSAの暗号化と復号化は,付加するパディングデータの作成や検証の手順などを組み入れた形で行われるため,それら全てを含めて仕様が決まる. 4 | 5 | - RSA-PKCS1v15: パディングとしてランダムの値を先頭に追加する. 6 | - RSA-OAEP (Optimal Asymmetric Encryption Padding): 任意のラベルのハッシュ値と決まった個数の0から作成した認証情報を平文の頭に追加してRSAで暗号化する.複合化ではRSAで復号した後,先頭に正しい「認証情報」が現れなければ「平文」を知ってる人が作成した暗号文ではない,適当に作られた暗号文であると判断しエラーを返すことができる.つまり選択暗号文攻撃に対して安全になる. 7 | -------------------------------------------------------------------------------- /public-key/rsa-oaep/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "crypto/rsa" 6 | "crypto/sha512" 7 | "fmt" 8 | "math/big" 9 | ) 10 | 11 | // (plain)^E mod N = cipher 12 | // public key = {E,N} 13 | // E means 'Encription', N means 'Number' 14 | 15 | // (cipher)^D mod N = plain 16 | // plivate key = {D,N} 17 | // D means 'Decription' 18 | func main() { 19 | 20 | // Generate key pair. public key {E,N} and private key {D,N} 21 | // E is 64437 https://en.wikipedia.org/wiki/65537_(number)) 22 | 23 | // size of key (bits) 24 | size := 2048 25 | 26 | // nprimes is the number of prime of which N consists 27 | // e.g., if nprimes is 2, N = p*q. If nprimes is 3, N = p*q*r 28 | nprimes := 2 29 | 30 | privateKey, err := rsa.GenerateKey(rand.Reader, size) 31 | if err != nil { 32 | fmt.Printf("err: %s", err) 33 | return 34 | } 35 | 36 | // N = p*q 37 | var z big.Int 38 | if privateKey.N.Cmp(z.Mul(privateKey.Primes[0], privateKey.Primes[1])) != 0 { 39 | panic("shoud not reach here") 40 | } 41 | 42 | plain := []byte("Bob loves Alice.") 43 | 44 | // A label is a byte string that is effectively bound to the ciphertext in a nonmalleable way. 45 | // http://crypto.stackexchange.com/questions/2074/rsa-oaep-input-parameters 46 | label := []byte("test") 47 | 48 | // Get public key from private key and encrypt 49 | publicKey := &privateKey.PublicKey 50 | cipherText, err := rsa.EncryptOAEP(sha512.New(), rand.Reader, publicKey, plain, label) 51 | if err != nil { 52 | fmt.Printf("Err: %s\n", err) 53 | return 54 | } 55 | fmt.Printf("Cipher: %x\n", cipherText) 56 | 57 | // Decrypt with private key 58 | plainText, err := rsa.DecryptOAEP(sha512.New(), rand.Reader, privateKey, cipherText, label) 59 | if err != nil { 60 | fmt.Printf("Err: %s\n", err) 61 | return 62 | } 63 | 64 | fmt.Printf("Plain: %s\n", plainText) 65 | } 66 | -------------------------------------------------------------------------------- /public-key/rsa-pkcs1v15/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "crypto/rsa" 6 | "fmt" 7 | ) 8 | 9 | // (plain)^E mod N = cipher 10 | // public key = {E,N} 11 | // E means 'Encription', N means 'Number' 12 | 13 | // (cipher)^D mod N = plain 14 | // plivate key = {D,N} 15 | // D means 'Decription' 16 | func main() { 17 | 18 | // Generate key pair. public key {E,N} and private key {D,N} 19 | // E is 64437 https://en.wikipedia.org/wiki/65537_(number)) 20 | 21 | // size of key (bits) 22 | size := 2048 23 | 24 | // nprimes is the number of prime of which N consists 25 | // e.g., if nprimes is 2, N = p*q. If nprimes is 3, N = p*q*r 26 | nprimes := 2 27 | 28 | privateKey, err := rsa.GenerateMultiPrimeKey(rand.Reader, nprimes, size) 29 | if err != nil { 30 | fmt.Printf("err: %s", err) 31 | return 32 | } 33 | 34 | plain := []byte("Bob loves Alice.") 35 | 36 | // Get public key from private key and encrypt 37 | publicKey := &privateKey.PublicKey 38 | 39 | // Why rand ? It's ude on nonZeroRandomBytes. 40 | // It fills the given slice with non-zero random octets. 41 | cipherText, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, plain) 42 | if err != nil { 43 | fmt.Printf("Err: %s\n", err) 44 | return 45 | } 46 | fmt.Printf("Cipher: %x\n", cipherText) 47 | 48 | // Decrypt with private key 49 | plainText, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, cipherText) 50 | if err != nil { 51 | fmt.Printf("Err: %s\n", err) 52 | return 53 | } 54 | 55 | fmt.Printf("Plain: %s\n", plainText) 56 | } 57 | -------------------------------------------------------------------------------- /signature/dsa/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/dsa" 5 | "crypto/rand" 6 | "fmt" 7 | ) 8 | 9 | func main() { 10 | var privateKey dsa.PrivateKey 11 | params := &privateKey.Parameters 12 | 13 | // L2048N224 is length of L and N 14 | if err := dsa.GenerateParameters(params, rand.Reader, dsa.L2048N224); err != nil { 15 | fmt.Printf("Err: %s", err) 16 | return 17 | } 18 | 19 | if err := dsa.GenerateKey(&privateKey, rand.Reader); err != nil { 20 | fmt.Printf("Err: %s", err) 21 | return 22 | } 23 | 24 | hashed := []byte("This is test hashed message") 25 | 26 | // It returns the signature as a pair of integers. 27 | r, s, err := dsa.Sign(rand.Reader, &privateKey, hashed) 28 | if err != nil { 29 | fmt.Printf("Err: %s", err) 30 | return 31 | } 32 | 33 | // Check signnature can be verified 34 | publicKey := &privateKey.PublicKey 35 | if dsa.Verify(publicKey, hashed, r, s) { 36 | fmt.Printf("Verified\n") 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /signature/ecdsa/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/ecdsa" 5 | "crypto/elliptic" 6 | "crypto/rand" 7 | "fmt" 8 | ) 9 | 10 | func main() { 11 | // 224-255 bits length key is same strenght with 2048 bits RSA 12 | priv, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader) 13 | if err != nil { 14 | fmt.Printf("Err: %s\n", err) 15 | return 16 | } 17 | 18 | hashed := []byte("This is message.") 19 | r, s, err := ecdsa.Sign(rand.Reader, priv, hashed) 20 | if err != nil { 21 | fmt.Printf("Err: %s\n", err) 22 | return 23 | } 24 | 25 | if ecdsa.Verify(&priv.PublicKey, hashed, r, s) { 26 | fmt.Printf("Verified!\n") 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /signature/rsa/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto" 5 | "crypto/rand" 6 | "crypto/rsa" 7 | "crypto/sha512" 8 | "fmt" 9 | ) 10 | 11 | func main() { 12 | size := 2024 13 | priv, err := rsa.GenerateKey(rand.Reader, size) 14 | if err != nil { 15 | fmt.Printf("Err: %s\n", err) 16 | return 17 | } 18 | 19 | msg := []byte("This is message.") 20 | hashed := sha512.Sum512(msg) 21 | s, err := rsa.SignPKCS1v15(rand.Reader, priv, crypto.SHA512, hashed[:]) 22 | if err != nil { 23 | fmt.Printf("Err: %s\n", err) 24 | return 25 | } 26 | fmt.Printf("Sign: %x\n", s) 27 | 28 | if err := rsa.VerifyPKCS1v15(&priv.PublicKey, crypto.SHA512, hashed[:], s); err != nil { 29 | fmt.Printf("Failed to verify: %s\n", err) 30 | return 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /symmetric-key/block/aes/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/aes" 5 | "fmt" 6 | ) 7 | 8 | func main() { 9 | // key length should be 16byte(AES-128), 24byte(AES-192) 10 | // 32byte (AES-256). In this case, AES-256 11 | aes256key := []byte("passw0rdpassw0rdpassw0rdpassw0rd") 12 | 13 | block, err := aes.NewCipher(aes256key) 14 | if err != nil { 15 | fmt.Printf("err: %s\n", err) 16 | return 17 | } 18 | 19 | // Encrypt 20 | plainText := []byte("This is 16 bytes") 21 | cipherText := make([]byte, len(plainText)) 22 | block.Encrypt(cipherText, plainText) 23 | fmt.Printf("Cipher text: %x\n", cipherText) 24 | 25 | // Decrypt 26 | decryptedText := make([]byte, len(cipherText)) 27 | block.Decrypt(decryptedText, cipherText) 28 | fmt.Printf("Decrypted text: %s\n", string(decryptedText)) 29 | } 30 | -------------------------------------------------------------------------------- /symmetric-key/block/des/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/cipher" 5 | "crypto/des" 6 | "crypto/rand" 7 | "fmt" 8 | "io" 9 | ) 10 | 11 | func main() { 12 | plainText := []byte("Bob loves Alice.") 13 | 14 | // Key must be 8 bytes 15 | key := []byte("passw0rd") 16 | 17 | // Create Cipher block for DES 18 | block, err := des.NewCipher(key) 19 | if err != nil { 20 | fmt.Printf("err: %s", err) 21 | } 22 | 23 | // Create initialization vector from rand.reader 24 | iv := make([]byte, des.BlockSize) 25 | if _, err := io.ReadFull(rand.Reader, iv); err != nil { 26 | fmt.Printf("err: %s", err) 27 | return 28 | } 29 | 30 | // Encrypt with CBC mode 31 | cipherText := make([]byte, len(plainText)) 32 | encryptMode := cipher.NewCBCEncrypter(block, iv) 33 | encryptMode.CryptBlocks(cipherText, plainText) 34 | fmt.Printf("Cipher text: %v\n", cipherText) 35 | 36 | // Decrypt with CBC mode 37 | decryptedText := make([]byte, len(cipherText)) 38 | decryptMode := cipher.NewCBCDecrypter(block, iv) 39 | decryptMode.CryptBlocks(decryptedText, cipherText) 40 | fmt.Printf("Decrypted text: %s\n", string(decryptedText)) 41 | } 42 | -------------------------------------------------------------------------------- /symmetric-key/block/tdes/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/cipher" 5 | "crypto/des" 6 | "crypto/rand" 7 | "fmt" 8 | "io" 9 | ) 10 | 11 | func main() { 12 | plainText := []byte("Bob loves Alice.") 13 | 14 | // Key must be 24(8*3) bytes because tdes runs des 3 times 15 | // plain text -> (DES encrypt) -> (DES decrypt) -> (DES encrypt) -> cipher text 16 | // DES-EDE2 uses the same key for first and the third encrypt 17 | // DES-EDE3 uses different key for all encrypt/decrypt 18 | key := []byte("passw0rdpassw0rdpassw0rd") 19 | 20 | // Create Cipher block for TDES 21 | block, err := des.NewTripleDESCipher(key) 22 | if err != nil { 23 | fmt.Printf("err: %s", err) 24 | return 25 | } 26 | 27 | // Create initialization vector from rand.reader 28 | iv := make([]byte, des.BlockSize) 29 | if _, err := io.ReadFull(rand.Reader, iv); err != nil { 30 | fmt.Printf("err: %s", err) 31 | return 32 | } 33 | 34 | // Encrypt with CBC mode 35 | cipherText := make([]byte, len(plainText)) 36 | encryptMode := cipher.NewCBCEncrypter(block, iv) 37 | encryptMode.CryptBlocks(cipherText, plainText) 38 | fmt.Printf("Cipher text: %v\n", cipherText) 39 | 40 | // Decrypt with CBC mode 41 | decryptedText := make([]byte, len(cipherText)) 42 | decryptMode := cipher.NewCBCDecrypter(block, iv) 43 | decryptMode.CryptBlocks(decryptedText, cipherText) 44 | fmt.Printf("Decrypted text: %s\n", string(decryptedText)) 45 | } 46 | -------------------------------------------------------------------------------- /symmetric-key/stream/rc4/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rc4" 5 | "fmt" 6 | ) 7 | 8 | func main() { 9 | plainText := []byte("Bob loves Alice.") 10 | 11 | key := []byte("passw0rd") 12 | cipher, err := rc4.NewCipher(key) 13 | if err != nil { 14 | fmt.Printf("err: %s\n", err) 15 | return 16 | } 17 | 18 | cipherText := make([]byte, len(plainText)) 19 | cipher.XORKeyStream(cipherText, plainText) 20 | fmt.Printf("Cipher text: %x\n", cipherText) 21 | 22 | decryptedText := make([]byte, len(cipherText)) 23 | cipher2, _ := rc4.NewCipher(key) 24 | cipher2.XORKeyStream(decryptedText, cipherText) 25 | fmt.Printf("Decrypted text: %s\n", string(decryptedText)) 26 | } 27 | -------------------------------------------------------------------------------- /tls/README.md: -------------------------------------------------------------------------------- 1 | # TLS 2 | 3 | golang `crypto/tls` implements TLS 1.2 4 | 5 | - client random + server random = pre-master secret 6 | - pre-master secret -> master secret 7 | 8 | master secret is used for symmetric key & Message Authentication Code(MAC) key & CBC Initial Vector(IV) 9 | 10 | 11 | ## client 12 | 13 | ### ClientHello 14 | 15 | ```golang 16 | var cipherSuites = []*cipherSuite{ 17 | // Ciphersuite order is chosen so that ECDHE comes before plain RSA 18 | // and RC4 comes before AES (because of the Lucky13 attack). 19 | {TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256..} 20 | {TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256..} 21 | {TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384..} 22 | {TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384..} 23 | {TLS_ECDHE_RSA_WITH_RC4_128_SHA..} 24 | {TLS_ECDHE_ECDSA_WITH_RC4_128_SHA..} 25 | {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA..} 26 | {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA..} 27 | {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA..} 28 | {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA..} 29 | {TLS_RSA_WITH_RC4_128_SHA..} 30 | {TLS_RSA_WITH_AES_128_CBC_SHA..} 31 | {TLS_RSA_WITH_AES_256_CBC_SHA..} 32 | {TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA..} 33 | {TLS_RSA_WITH_3DES_EDE_CBC_SHA..} 34 | } 35 | ``` 36 | 37 | ### Certificate 38 | 39 | ```golang 40 | func (hs *clientHandshakeState) doFullHandshake() error 41 | ``` 42 | 43 | ```golang 44 | msg, err := c.readHandshake() 45 | if err != nil { 46 | return err 47 | } 48 | 49 | certMsg, ok := msg.(*certificateMsg) 50 | 51 | certs := make([]*x509.Certificate, len(certMsg.certificates)) 52 | for i, asn1Data := range certMsg.certificates { 53 | cert, err := x509.ParseCertificate(asn1Data) 54 | if err != nil { 55 | c.sendAlert(alertBadCertificate) 56 | return errors.New("tls: failed to parse certificate from server: " + err.Error()) 57 | } 58 | certs[i] = cert 59 | } 60 | 61 | if !c.config.InsecureSkipVerify { 62 | opts := x509.VerifyOptions{ 63 | Roots: c.config.RootCAs, 64 | CurrentTime: c.config.time(), 65 | DNSName: c.config.ServerName, 66 | Intermediates: x509.NewCertPool(), 67 | } 68 | 69 | for i, cert := range certs { 70 | if i == 0 { 71 | continue 72 | } 73 | opts.Intermediates.AddCert(cert) 74 | } 75 | c.verifiedChains, err = certs[0].Verify(opts) 76 | if err != nil { 77 | c.sendAlert(alertBadCertificate) 78 | return err 79 | } 80 | } 81 | ``` 82 | 83 | ### preMasterSecret (RSA) 84 | 85 | On client side (ecrypt by public key), 86 | 87 | ```golang 88 | func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) { 89 | preMasterSecret := make([]byte, 48) 90 | preMasterSecret[0] = byte(clientHello.vers >> 8) 91 | preMasterSecret[1] = byte(clientHello.vers) 92 | _, err := io.ReadFull(config.rand(), preMasterSecret[2:]) 93 | if err != nil { 94 | return nil, nil, err 95 | } 96 | 97 | encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), preMasterSecret) 98 | if err != nil { 99 | return nil, nil, err 100 | } 101 | ckx := new(clientKeyExchangeMsg) 102 | ckx.ciphertext = make([]byte, len(encrypted)+2) 103 | ckx.ciphertext[0] = byte(len(encrypted) >> 8) 104 | ckx.ciphertext[1] = byte(len(encrypted)) 105 | copy(ckx.ciphertext[2:], encrypted) 106 | return preMasterSecret, ckx, nil 107 | } 108 | ``` 109 | 110 | On server side (decrypt by private key), 111 | 112 | ```golang 113 | func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) { 114 | if len(ckx.ciphertext) < 2 { 115 | return nil, errClientKeyExchange 116 | } 117 | 118 | ciphertext := ckx.ciphertext 119 | if version != VersionSSL30 { 120 | ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1]) 121 | if ciphertextLen != len(ckx.ciphertext)-2 { 122 | return nil, errClientKeyExchange 123 | } 124 | ciphertext = ckx.ciphertext[2:] 125 | } 126 | priv, ok := cert.PrivateKey.(crypto.Decrypter) 127 | if !ok { 128 | return nil, errors.New("tls: certificate private key does not implement crypto.Decrypter") 129 | } 130 | // Perform constant time RSA PKCS#1 v1.5 decryption 131 | preMasterSecret, err := priv.Decrypt(config.rand(), ciphertext, &rsa.PKCS1v15DecryptOptions{SessionKeyLen: 48}) 132 | if err != nil { 133 | return nil, err 134 | } 135 | 136 | return preMasterSecret, nil 137 | } 138 | ``` 139 | 140 | ### masterSecret 141 | 142 | 143 | ```golang 144 | hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.ran\ 145 | dom) 146 | ``` 147 | 148 | ```golang 149 | // masterFromPreMasterSecret generates the master secret from the pre-master 150 | // secret. See http://tools.ietf.org/html/rfc5246#section-8.1 151 | func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, clientRandom, serverRandom []byte)[]byte { 152 | var seed [tlsRandomLength * 2]byte 153 | copy(seed[0:len(clientRandom)], clientRandom) 154 | copy(seed[len(clientRandom):], serverRandom) 155 | masterSecret := make([]byte, masterSecretLength) 156 | prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed[0:]) 157 | return masterSecret 158 | } 159 | ``` 160 | 161 | ## MAC 162 | 163 | ```golang 164 | // macSHA1 returns a macFunction for the given protocol version. 165 | func macSHA1(version uint16, key []byte) macFunction { 166 | if version == VersionSSL30 { 167 | mac := ssl30MAC{ 168 | h: sha1.New(), 169 | key: make([]byte, len(key)), 170 | } 171 | copy(mac.key, key) 172 | return mac 173 | } 174 | return tls10MAC{hmac.New(sha1.New, key)} 175 | } 176 | ``` 177 | -------------------------------------------------------------------------------- /tls/client.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "crypto/tls" 6 | "crypto/x509" 7 | "fmt" 8 | "io" 9 | "io/ioutil" 10 | "log" 11 | "path/filepath" 12 | ) 13 | 14 | func main() { 15 | // Read CA certificate 16 | caFile, _ := filepath.Abs("../certificate/x509/ecdsa/certs/ca.pem") 17 | rootPem, err := ioutil.ReadFile(caFile) 18 | if err != nil { 19 | fmt.Printf("Err: %s\n", err) 20 | return 21 | } 22 | 23 | roots := x509.NewCertPool() 24 | if ok := roots.AppendCertsFromPEM(rootPem); !ok { 25 | fmt.Printf("Err: failed to parse root certificate") 26 | return 27 | } 28 | 29 | config := tls.Config{ 30 | RootCAs: roots, 31 | } 32 | 33 | conn, err := tls.Dial("tcp", "127.0.0.1:443", &config) 34 | if err != nil { 35 | log.Printf("[ERROR] %s\n", err) 36 | return 37 | } 38 | defer conn.Close() 39 | 40 | log.Printf("[INFO] Connect to %s", conn.RemoteAddr()) 41 | 42 | state := conn.ConnectionState() 43 | log.Printf("[INFO] Handshake complete: %v", state.HandshakeComplete) 44 | for _, c := range state.PeerCertificates { 45 | k, _ := x509.MarshalPKIXPublicKey(c.PublicKey) 46 | log.Printf("[INFO] Cert: Public key: %x...", k[:20]) 47 | log.Printf("[INFO] Cert: Organization: %s", c.Subject.Organization[0]) 48 | } 49 | 50 | message := []byte("Hello") 51 | if _, err := conn.Write(message); err != nil { 52 | log.Printf("[ERROR] Write: %s", err) 53 | return 54 | } 55 | 56 | var buf bytes.Buffer 57 | if _, err := io.Copy(&buf, conn); err != nil { 58 | log.Printf("[ERROR] Read: %s", err) 59 | return 60 | } 61 | log.Printf("[INFO] Reply: %s", buf.String()) 62 | } 63 | -------------------------------------------------------------------------------- /tls/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/tls" 5 | "fmt" 6 | "io" 7 | "log" 8 | "net" 9 | "path/filepath" 10 | ) 11 | 12 | func main() { 13 | certFile, _ := filepath.Abs("../certificate/x509/ecdsa/certs/server.pem") 14 | keyFile, _ := filepath.Abs("../certificate/x509/ecdsa/certs/server-key.pem") 15 | cert, err := tls.LoadX509KeyPair(certFile, keyFile) 16 | if err != nil { 17 | log.Printf("Err: %s\n", err) 18 | return 19 | } 20 | 21 | config := tls.Config{ 22 | ClientAuth: tls.NoClientCert, 23 | Certificates: []tls.Certificate{cert}, 24 | } 25 | 26 | ln, err := tls.Listen("tcp", "localhost:443", &config) 27 | if err != nil { 28 | log.Printf("Err: %s\n", err) 29 | return 30 | } 31 | log.Println("[INFO] Server listening") 32 | 33 | for { 34 | conn, err := ln.Accept() 35 | if err != nil { 36 | fmt.Printf("Err: %s\n", err) 37 | return 38 | } 39 | log.Printf("[INFO] Request from %s", conn.RemoteAddr()) 40 | 41 | go func(c net.Conn) { 42 | defer c.Close() 43 | 44 | tlsconn, ok := c.(*tls.Conn) 45 | if !ok { 46 | log.Printf("[ERROR] Connection should be TLS") 47 | return 48 | } 49 | 50 | buf := make([]byte, 1024) 51 | n, err := tlsconn.Read(buf) 52 | if err != nil { 53 | if err != io.EOF { 54 | log.Printf("[ERROR] Read: %s", err) 55 | return 56 | } 57 | } 58 | log.Printf("[INFO] Message from client (%d byte): %s", n, string(buf[:n])) 59 | 60 | state := tlsconn.ConnectionState() 61 | log.Printf("[INFO] Handshake complete: %v", state.HandshakeComplete) 62 | 63 | if _, err := tlsconn.Write([]byte("Hello with TLS\n")); err != nil { 64 | log.Printf("[ERROR] Write: %s", err) 65 | return 66 | } 67 | }(conn) 68 | } 69 | } 70 | --------------------------------------------------------------------------------