Go言語と暗号技術(AESからTLS)

by Taichi Nakashima,

TCP/IP SSL/TLSGocrypto/

cryptoGotcnksm/go-crypto


2

GoDESData Encryption StandardDEStriple-DESAESAdvanced Encryption Standard RC4

AESDES使plainTextAES/
plainText := []byte("This is 16 bytes")

key := []byte("passw0rdpassw0rdpassw0rdpassw0rd")

block, err := aes.NewCipher(key)
if err != nil {
    fmt.Printf("err: %s\n", err)
    return
}

// Encrypt
cipherText := make([]byte, len(plainText))
block.Encrypt(cipherText, plainText)
fmt.Printf("Cipher text: %x\n", cipherText)

// Decrypt
decryptedText := make([]byte, len(cipherText))
block.Decrypt(decryptedText, cipherText)
fmt.Printf("Decrypted text: %s\n", string(decryptedText))

AES16byte24byte32byteAES-128AES-192AES-256NewCiphercipher.BlockEncrypt()Decrypt()

AES16byte/16byte使




ECBElectronic CodeBook mode

Gocipher


CBCCipher Block Chainning - 1XOR1IVInitialization VectorXORSSL/TLS3DES_EDE_CBCAES_256_CBC

CFBCipher FeedBack - 1Key StreamXOR

OFBOutput FeedBack - 1Key StreamKey StreamXORKey StreamKey Stream11

CTRCounTeR - 1Key StreamKey Stream11Key Stream

GCMGalois/Counter - CTRTLS1.2使IVAEADAuthenticated Encryption with Associated Data


CFBOFBCTR使

AES+CTRplainText/16byte使
plainText := []byte("Bob loves Alice. But Alice hate Bob...")

key := []byte("passw0rdpassw0rdpassw0rdpassw0rd")

// Create new AES cipher block
block, err := aes.NewCipher(key)
if err != nil {
    fmt.Printf("err: %s\n", err)
}

// Create IV
cipherText := make([]byte, aes.BlockSize+len(plainText))
iv := cipherText[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
    fmt.Printf("err: %s\n", err)
}

// Encrypt
encryptStream := cipher.NewCTR(block, iv)
encryptStream.XORKeyStream(cipherText[aes.BlockSize:], plainText)
fmt.Printf("Cipher text: %x \n", cipherText)

// Decrpt
decryptedText := make([]byte, len(cipherText[aes.BlockSize:]))
decryptStream := cipher.NewCTR(block, cipherText[:aes.BlockSize])
decryptStream.XORKeyStream(decryptedText, cipherText[aes.BlockSize:])
fmt.Printf("Decrypted text: %s\n", string(decryptedText))

NewCiphercipher.BlockNewCTRIVNewCTRcipher.Stream//


GoRSAElliptic Curve

RSARSAGo


RSA-PKCS1v15 - 

RSA-OAEP (Optimal Asymmetric Encryption Padding) - 0RSARSA


RSA-PKCS1v15plainText/
plainText := []byte("Bob loves Alice.")

// size of key (bits)
size := 2048

// Generate private and public key pair
privateKey, err := rsa.GenerateKey(rand.Reader, size)
if err != nil {
    fmt.Printf("err: %s", err)
    return
}

// Get public key from private key and encrypt
publicKey := &privateKey.PublicKey

cipherText, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, plainText)
if err != nil {
    fmt.Printf("Err: %s\n", err)
    return
}
fmt.Printf("Cipher text: %x\n", cipherText)

// Decrypt with private key
decryptedText, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, cipherText)
if err != nil {
    fmt.Printf("Err: %s\n", err)
    return
}
    
fmt.Printf("Decrypted text: %s\n", decryptedText)

GenerateKeyPrivateKeyEncryptPKCS1v15DecryptPKCS1v15/

10242048203040962031使


使

GoMD5SHA-1SHA-2SHA-224SHA-256SHA-384SHA-512SHA-512/224SHA-512/256golang.org/x/cryptoAESSHA-3Keccak

SHA-512使msg
msg := []byte("Bob is dead")
checksum512 := sha512.Sum512(msg)

実際にSHA-3を使いmsgからハッシュ値を計算する.

msg := []byte("Alice is dead")
// A MAC with 64 bytes of output has 512-bit security strength
h := make([]byte, 64)

d := sha3.NewShake256()
d.Write(msg)

d.Read(h)

SHA-1SHA-2SHA-3ShakeHash使

SHA-1使SHA-2SHA-3使

使

MAC


MACMAC

GoHMAC

HMAC使msgkeyMACHMAChash.Hash使SHA-512
msg := []byte("Bob loves Alice.")
key := []byte("passw0rd")

h1 := hmac.New(sha512.New, key)
h1.Write(msg)
mac1 := h1.Sum(nil)
fmt.Printf("MAC1: %x\n", mac1)

h2 := hmac.New(sha512.New, key)
h2.Write(msg)
mac2 := h2.Sum(nil)
fmt.Printf("MAC2: %x\n", mac2)

fmt.Printf("Valid? %v\n", hmac.Equal(mac1, mac2))

MACMACMAC




GoDSADigital Signature AlgorithmRSA

使
priv, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
if err != nil {
    fmt.Printf("Err: %s\n", err)
    return
}

hashed := []byte("This is message.")
r, s, err := ecdsa.Sign(rand.Reader, priv, hashed)
if err != nil {
    fmt.Printf("Err: %s\n", err)
    return
}

if ecdsa.Verify(&priv.PublicKey, hashed, r, s) {
    fmt.Printf("Verified!\n")
}

crypto/ellipticcrypto/ecdsaGenerateKeyP-224P-256P-384P-521Signbig.Int

x509


man-in-the-middleCA

X.509Gocrypto/x509X.509

X.509ASN.1Abstract Syntax Notation OneASN.1 EncodeX.509DERDistinguished Encoding RulesEncodeEncodeGoencoding/ans1DEREncoderASN.1low levelcrypto/x509/pkixPEMPrivacy Enhanced MailEncodeencoding/pem

crypto/x509RSA-PKCS1v15ASN.1 DERMarshal/Unmarshal

GoX.509使PEMca.pem
// Generate pub & priv key pair by Elliptic Curve Digital Signature
priv, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
if err != nil {
    fmt.Printf("Err: %s\n", err)
    return
}

// Create CA certificate template
ca := x509.Certificate{
    IsCA:         true,
    SerialNumber: big.NewInt(1234),
    Subject: pkix.Name{
        Country:      []string{"Japan"},
        Organization: []string{"TCNKSM ECDSA CA Inc."},
    },

    NotBefore: time.Now(),
    NotAfter:  time.Now().Add(24 * time.Hour),

    KeyUsage:              x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageCertSign,
    ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
    BasicConstraintsValid: true,
}

// Create Certificate
derBytes, err := x509.CreateCertificate(rand.Reader, &ca, &ca, &priv.PublicKey, priv)
if err != nil {
    fmt.Printf("Err: %s\n", err)
    return
}

certOut, err := os.Create("ca.pem")
if err != nil {
    fmt.Printf("Err: %s\n", err)
    return
}
defer certOut.Close()

if err := pem.Encode(certOut, &pem.Block{
    Type:  "CERTIFICATE",
    Bytes: derBytes,
}); err != nil {
    fmt.Printf("Err: %s\n", err)
    return
}

x509.Certificatestructx509.CreateCertificate

crypto/x509crypto/tlsgenerate_cert.go

TLS


TLScryptoTLSHMAC

pre-master secretmaster secret/RSAkey-agreement
encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), preMasterSecret)
preMasterSecret, err := priv.Decrypt(config.rand(), ciphertext, &rsa.PKCS1v15DecryptOptions{SessionKeyLen: 48})

TLS使https


GoTLScrypto/tls