-
Notifications
You must be signed in to change notification settings - Fork 15
/
crypto.go
86 lines (69 loc) · 1.94 KB
/
crypto.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package widevine
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/sha1"
"encoding/base64"
"encoding/hex"
"errors"
"fmt"
)
// Crypto struct.
type Crypto struct {
Key []byte
IV []byte
}
// NewCrypto creates a Crypto instance with key and iv.
func NewCrypto(key []byte, iv []byte) *Crypto {
c := &Crypto{
Key: key,
IV: iv,
}
return c
}
func (c *Crypto) generateSignature(payload []byte) string {
h := sha1.New()
h.Write([]byte(payload))
bs := h.Sum(nil)
hash := fmt.Sprintf("%x", bs)
// Create signature.
ciphertext := c.encrypt(hash)
return ciphertext
}
func (c *Crypto) encrypt(text string) string {
// See: https://golang.org/pkg/crypto/cipher/#NewCBCEncrypter
textDec, _ := hex.DecodeString(text)
plaintext := pad([]byte(textDec))
if len(plaintext)%aes.BlockSize != 0 {
panic("plaintext is not a multiple of the block size")
}
block, err := aes.NewCipher(c.Key)
if err != nil {
panic(err)
}
ciphertext := make([]byte, aes.BlockSize+len(plaintext))
mode := cipher.NewCBCEncrypter(block, c.IV)
mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext)
enc := base64.StdEncoding.EncodeToString([]byte(ciphertext[aes.BlockSize:]))
return enc
}
// Pads src to a multiple of aes.Blocksize (16) using PKCS #7 standard block padding.
// See http://tools.ietf.org/html/rfc5652#section-6.3.
func pad(src []byte) []byte {
padding := aes.BlockSize - len(src)%aes.BlockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(src, padtext...)
}
// Removes PKCS #7 standard block padding from src.
// See http://tools.ietf.org/html/rfc5652#section-6.3.
// This function is the inverse of pad.
// If the padding is not well-formed, unpad returns nil.
func unpad(src []byte) ([]byte, error) {
length := len(src)
unpadding := int(src[length-1])
if unpadding > length {
return nil, errors.New("unpad error. This could happen when incorrect encryption key is used")
}
return src[:(length - unpadding)], nil
}