// DeriveConcatKDF implements NIST SP 800-56A Concatenation Key Derivation Function. Derives // key material of keydatalen bits size given Z (sharedSecret), OtherInfo (AlgorithmID | // PartyUInfo | PartyVInfo | SuppPubInfo | SuppPrivInfo) and hash function func DeriveConcatKDF(keydatalen int, sharedSecret, algId, partyUInfo, partyVInfo, suppPubInfo, suppPrivInfo []byte, h hash.Hash) []byte { otherInfo := arrays.Concat(algId, partyUInfo, partyVInfo, suppPubInfo, suppPrivInfo) keyLenBytes := keydatalen >> 3 reps := int(math.Ceil(float64(keyLenBytes) / float64(h.Size()))) if reps > MaxInt { panic("kdf.DeriveConcatKDF: too much iterations (more than 2^32-1).") } dk := make([]byte, 0, keyLenBytes) for counter := 1; counter <= reps; counter++ { h.Reset() counterBytes := arrays.UInt32ToBytes(uint32(counter)) h.Write(counterBytes) h.Write(sharedSecret) h.Write(otherInfo) dk = h.Sum(dk) } return dk[:keyLenBytes] }
func (alg *AesCbcHmac) computeAuthTag(aad []byte, iv []byte, cipherText []byte, hmacKey []byte) (signature []byte) { al := arrays.UInt64ToBytes(uint64(len(aad) << 3)) hmacInput := arrays.Concat(aad, iv, cipherText, al) hmac := calculateHmac(alg.keySizeBits, hmacInput, hmacKey) return hmac[0 : len(hmac)/2] }
func (alg *Pbse2HmacAesKW) Unwrap(encryptedCek []byte, key interface{}, cekSizeBits int, header map[string]interface{}) (cek []byte, err error) { if passphrase, ok := key.(string); ok { var p2s string var p2c float64 if p2c, ok = header["p2c"].(float64); !ok { return nil, errors.New("Pbse2HmacAesKW.Unwrap(): expected 'p2c' param in JWT header, but was not found.") } if p2s, ok = header["p2s"].(string); !ok { return nil, errors.New("Pbse2HmacAesKW.Unwrap(): expected 'p2s' param in JWT header, but was not found.") } var saltInput []byte algId := []byte(header["alg"].(string)) if saltInput, err = base64url.Decode(p2s); err != nil { return nil, err } salt := arrays.Concat(algId, []byte{0}, saltInput) kek := kdf.DerivePBKDF2([]byte(passphrase), salt, int(p2c), alg.keySizeBits, alg.prf()) return alg.aesKW.Unwrap(encryptedCek, kek, cekSizeBits, header) } return nil, errors.New("Pbse2HmacAesKW.Unwrap(): expected key to be 'string' array") }
// KeyWrap encrypts provided key (CEK) with KEK key using AES Key Wrap (rfc 3394) algorithm func KeyWrap(cek, kek []byte) ([]byte, error) { // 1) Initialize variables a := defaultIV // Set A = IV, an initial value r := arrays.Slice(cek, 8) // For i = 1 to n // R[0][i] = P[i] n := uint64(len(r)) // 2) Calculate intermediate values. var j, i, t uint64 for j = 0; j < 6; j++ { // For j = 0 to 5 for i = 0; i < n; i++ { // For i=1 to n t = n*j + i + 1 b, e := aesEnc(kek, arrays.Concat(a, r[i])) // B=AES(K, A | R[i]) if e != nil { return nil, e } a = b[:len(b)/2] // A=MSB(64,B) ^ t where t = (n*j)+i r[i] = b[len(b)/2:] // R[i] = LSB(64, B) a = arrays.Xor(a, arrays.UInt64ToBytes(t)) } } // 3) Output the results c := make([][]byte, n+1, n+1) c[0] = a // Set C[0] = A for i = 1; i <= n; i++ { // For i = 1 to n c[i] = r[i-1] // C[i] = R[i] } return arrays.Unwrap(c), nil }
// KeyUnwrap decrypts previously encrypted key (CEK) with KEK key using AES Key Wrap (rfc 3394) algorithm func KeyUnwrap(encryptedCek, kek []byte) ([]byte, error) { // 1) Initialize variables c := arrays.Slice(encryptedCek, 8) a := c[0] // Set A = C[0] r := make([][]byte, len(c)-1) for i := 1; i < len(c); i++ { // For i = 1 to n r[i-1] = c[i] // R[i] = C[i] } n := uint64(len(r)) // 2) Calculate intermediate values var t, j uint64 for j = 6; j > 0; j-- { // For j = 5 to 0 for i := n; i > 0; i-- { // For i = n to 1 t = n*(j-1) + i a = arrays.Xor(a, arrays.UInt64ToBytes(t)) b, e := aesDec(kek, arrays.Concat(a, r[i-1])) // B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i if e != nil { return nil, e } a = b[:len(b)/2] // A = MSB(64, B) r[i-1] = b[len(b)/2:] // R[i] = LSB(64, B) } } // 3) Output the results if !hmac.Equal(defaultIV, a) { // If A is an appropriate initial value return nil, errors.New("aes.KeyUnwrap(): integrity check failed.") } // For i = 1 to n return arrays.Unwrap(r), nil // P[i] = R[i] }
func (alg *EcdsaUsingSha) Sign(securedInput []byte, key interface{}) (signature []byte, err error) { if privKey, ok := key.(*ecdsa.PrivateKey); ok { if sizeBits := privKey.Curve.Params().BitSize; sizeBits != alg.keySizeBits { return nil, errors.New(fmt.Sprintf("EcdsaUsingSha.Sign(): expected key of size %v bits, but was given %v bits.", alg.keySizeBits, sizeBits)) } var r, s *big.Int if r, s, err = ecdsa.Sign(rand.Reader, privKey, sha(alg.hashSizeBits, securedInput)); err == nil { rBytes := padding.Align(r.Bytes(), alg.keySizeBits) sBytes := padding.Align(s.Bytes(), alg.keySizeBits) return arrays.Concat(rBytes, sBytes), nil } return nil, err } return nil, errors.New("EcdsaUsingSha.Sign(): expects key to be '*ecdsa.PrivateKey'") }
func (alg *Pbse2HmacAesKW) WrapNewKey(cekSizeBits int, key interface{}, header map[string]interface{}) (cek []byte, encryptedCek []byte, err error) { if passphrase, ok := key.(string); ok { algId := []byte(header["alg"].(string)) iterationCount := 8192 var saltInput []byte if saltInput, err = arrays.Random(12); err != nil { return nil, nil, err } header["p2c"] = iterationCount header["p2s"] = base64url.Encode(saltInput) salt := arrays.Concat(algId, []byte{0}, saltInput) kek := kdf.DerivePBKDF2([]byte(passphrase), salt, iterationCount, alg.keySizeBits, alg.prf()) return alg.aesKW.WrapNewKey(cekSizeBits, kek, header) } return nil, nil, errors.New("Pbse2HmacAesKW.WrapNewKey(): expected key to be 'string' array") }
func prependDatalen(bytes []byte) []byte { return arrays.Concat(arrays.UInt32ToBytes(uint32(len(bytes))), bytes) }