...
1
16
17 package josecipher
18
19 import (
20 "crypto/cipher"
21 "crypto/subtle"
22 "encoding/binary"
23 "errors"
24 )
25
26 var defaultIV = []byte{0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6}
27
28
29 func KeyWrap(block cipher.Block, cek []byte) ([]byte, error) {
30 if len(cek)%8 != 0 {
31 return nil, errors.New("go-jose/go-jose: key wrap input must be 8 byte blocks")
32 }
33
34 n := len(cek) / 8
35 r := make([][]byte, n)
36
37 for i := range r {
38 r[i] = make([]byte, 8)
39 copy(r[i], cek[i*8:])
40 }
41
42 buffer := make([]byte, 16)
43 tBytes := make([]byte, 8)
44 copy(buffer, defaultIV)
45
46 for t := 0; t < 6*n; t++ {
47 copy(buffer[8:], r[t%n])
48
49 block.Encrypt(buffer, buffer)
50
51 binary.BigEndian.PutUint64(tBytes, uint64(t+1))
52
53 for i := 0; i < 8; i++ {
54 buffer[i] = buffer[i] ^ tBytes[i]
55 }
56 copy(r[t%n], buffer[8:])
57 }
58
59 out := make([]byte, (n+1)*8)
60 copy(out, buffer[:8])
61 for i := range r {
62 copy(out[(i+1)*8:], r[i])
63 }
64
65 return out, nil
66 }
67
68
69 func KeyUnwrap(block cipher.Block, ciphertext []byte) ([]byte, error) {
70 if len(ciphertext)%8 != 0 {
71 return nil, errors.New("go-jose/go-jose: key wrap input must be 8 byte blocks")
72 }
73
74 n := (len(ciphertext) / 8) - 1
75 r := make([][]byte, n)
76
77 for i := range r {
78 r[i] = make([]byte, 8)
79 copy(r[i], ciphertext[(i+1)*8:])
80 }
81
82 buffer := make([]byte, 16)
83 tBytes := make([]byte, 8)
84 copy(buffer[:8], ciphertext[:8])
85
86 for t := 6*n - 1; t >= 0; t-- {
87 binary.BigEndian.PutUint64(tBytes, uint64(t+1))
88
89 for i := 0; i < 8; i++ {
90 buffer[i] = buffer[i] ^ tBytes[i]
91 }
92 copy(buffer[8:], r[t%n])
93
94 block.Decrypt(buffer, buffer)
95
96 copy(r[t%n], buffer[8:])
97 }
98
99 if subtle.ConstantTimeCompare(buffer[:8], defaultIV) == 0 {
100 return nil, errors.New("go-jose/go-jose: failed to unwrap key")
101 }
102
103 out := make([]byte, n*8)
104 for i := range r {
105 copy(out[i*8:], r[i])
106 }
107
108 return out, nil
109 }
110
View as plain text