concat_kdf.go (1870B)
1 /*- 2 * Copyright 2014 Square Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package josecipher 18 19 import ( 20 "crypto" 21 "encoding/binary" 22 "hash" 23 "io" 24 ) 25 26 type concatKDF struct { 27 z, info []byte 28 i uint32 29 cache []byte 30 hasher hash.Hash 31 } 32 33 // NewConcatKDF builds a KDF reader based on the given inputs. 34 func NewConcatKDF(hash crypto.Hash, z, algID, ptyUInfo, ptyVInfo, supPubInfo, supPrivInfo []byte) io.Reader { 35 buffer := make([]byte, uint64(len(algID))+uint64(len(ptyUInfo))+uint64(len(ptyVInfo))+uint64(len(supPubInfo))+uint64(len(supPrivInfo))) 36 n := 0 37 n += copy(buffer, algID) 38 n += copy(buffer[n:], ptyUInfo) 39 n += copy(buffer[n:], ptyVInfo) 40 n += copy(buffer[n:], supPubInfo) 41 copy(buffer[n:], supPrivInfo) 42 43 hasher := hash.New() 44 45 return &concatKDF{ 46 z: z, 47 info: buffer, 48 hasher: hasher, 49 cache: []byte{}, 50 i: 1, 51 } 52 } 53 54 func (ctx *concatKDF) Read(out []byte) (int, error) { 55 copied := copy(out, ctx.cache) 56 ctx.cache = ctx.cache[copied:] 57 58 for copied < len(out) { 59 ctx.hasher.Reset() 60 61 // Write on a hash.Hash never fails 62 _ = binary.Write(ctx.hasher, binary.BigEndian, ctx.i) 63 _, _ = ctx.hasher.Write(ctx.z) 64 _, _ = ctx.hasher.Write(ctx.info) 65 66 hash := ctx.hasher.Sum(nil) 67 chunkCopied := copy(out[copied:], hash) 68 copied += chunkCopied 69 ctx.cache = hash[chunkCopied:] 70 71 ctx.i++ 72 } 73 74 return copied, nil 75 }