github.com/zntrio/harp/v2@v2.0.9/pkg/sdk/security/crypto/rfc6979/rfc6979.go (about) 1 // Licensed to Elasticsearch B.V. under one or more contributor 2 // license agreements. See the NOTICE file distributed with 3 // this work for additional information regarding copyright 4 // ownership. Elasticsearch B.V. licenses this file to you under 5 // the Apache License, Version 2.0 (the "License"); you may 6 // not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, 12 // software distributed under the License is distributed on an 13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 // KIND, either express or implied. See the License for the 15 // specific language governing permissions and limitations 16 // under the License. 17 18 package rfc6979 19 20 // From https://github.com/codahale/rfc6979 21 22 import ( 23 "bytes" 24 "crypto/hmac" 25 "hash" 26 "math/big" 27 ) 28 29 // https://tools.ietf.org/html/rfc6979#section-3.2 30 func generateSecret(q, x *big.Int, alg func() hash.Hash, digest []byte, test func(*big.Int) bool) { 31 qlen := q.BitLen() 32 holen := alg().Size() 33 rolen := (qlen + 7) >> 3 34 bx := append(int2octets(x, rolen), bits2octets(digest, q, qlen, rolen)...) 35 36 // Step B 37 v := bytes.Repeat([]byte{0x01}, holen) 38 39 // Step C 40 k := bytes.Repeat([]byte{0x00}, holen) 41 42 // Step D 43 k = mac(alg, k, append(append(v, 0x00), bx...), k) 44 45 // Step E 46 v = mac(alg, k, v, v) 47 48 // Step F 49 k = mac(alg, k, append(append(v, 0x01), bx...), k) 50 51 // Step G 52 v = mac(alg, k, v, v) 53 54 // Step H 55 for { 56 // Step H1 57 var t []byte 58 59 // Step H2 60 for len(t) < qlen/8 { 61 v = mac(alg, k, v, v) 62 t = append(t, v...) 63 } 64 65 // Step H3 66 secret := bits2int(t, qlen) 67 if secret.Cmp(one) >= 0 && secret.Cmp(q) < 0 && test(secret) { 68 return 69 } 70 k = mac(alg, k, append(v, 0x00), k) 71 v = mac(alg, k, v, v) 72 } 73 } 74 75 // ----------------------------------------------------------------------------- 76 77 // mac returns an HMAC of the given key and message. 78 func mac(alg func() hash.Hash, k, m, buf []byte) []byte { 79 h := hmac.New(alg, k) 80 h.Write(m) 81 return h.Sum(buf[:0]) 82 } 83 84 // https://tools.ietf.org/html/rfc6979#section-2.3.2 85 func bits2int(in []byte, qlen int) *big.Int { 86 vlen := len(in) * 8 87 v := new(big.Int).SetBytes(in) 88 if vlen > qlen { 89 v = new(big.Int).Rsh(v, uint(vlen-qlen)) 90 } 91 return v 92 } 93 94 // https://tools.ietf.org/html/rfc6979#section-2.3.3 95 func int2octets(v *big.Int, rolen int) []byte { 96 out := v.Bytes() 97 98 // pad with zeros if it's too short 99 if len(out) < rolen { 100 out2 := make([]byte, rolen) 101 copy(out2[rolen-len(out):], out) 102 return out2 103 } 104 105 // drop most significant bytes if it's too long 106 if len(out) > rolen { 107 out2 := make([]byte, rolen) 108 copy(out2, out[len(out)-rolen:]) 109 return out2 110 } 111 112 return out 113 } 114 115 // https://tools.ietf.org/html/rfc6979#section-2.3.4 116 func bits2octets(in []byte, q *big.Int, qlen, rolen int) []byte { 117 z1 := bits2int(in, qlen) 118 z2 := new(big.Int).Sub(z1, q) 119 if z2.Sign() < 0 { 120 return int2octets(z1, rolen) 121 } 122 return int2octets(z2, rolen) 123 } 124 125 var one = big.NewInt(1)