1 // Copyright 2016 Google LLC. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package fixchain 16 17 import ( 18 "crypto/sha256" 19 "sort" 20 21 "github.com/google/certificate-transparency-go/x509" 22 ) 23 24 const hashSize = sha256.Size 25 26 var newHash = sha256.New 27 28 func hash(c *x509.Certificate) (hash [hashSize]byte) { 29 copy(hash[:], newHash().Sum(c.Raw)) 30 return 31 } 32 33 func hashChain(ch []*x509.Certificate) (hash [hashSize]byte) { 34 h := newHash() 35 for _, c := range ch { 36 h.Write(newHash().Sum(c.Raw)) 37 } 38 copy(hash[:], h.Sum(nil)) 39 return 40 } 41 42 // hashBag hashes all of the certs in the chain, irrespective of their order. 43 // Chains containing the same certs in the same order with no duplicates will 44 // result in the same hash. Chains containing the same certs in different orders 45 // with no duplicates will result in the same hash. Chains containing the same 46 // certs (either in the same order or in different orders) that contain exactly 47 // the same duplicated certs, will result in the same hash. If chains contain 48 // the same certs (either in the same order or in different orders) and some 49 // certs are duplicated, but the specific certs that are duplicated differ 50 // and/or the number of times they are duplicated differ, these chains will 51 // result in different hashes. 52 func hashBag(chain []*x509.Certificate) [hashSize]byte { 53 b := bag{certs: make([]*x509.Certificate, len(chain))} 54 copy(b.certs, chain) 55 sort.Sort(b) 56 return hashChain(b.certs) 57 } 58 59 // bag is a collection of certificates that can contain duplicates. 60 // Applying sort will order them by their raw representation. 61 type bag struct { 62 certs []*x509.Certificate 63 } 64 65 // Len implements sort.Sort(data Interface) for bag. 66 func (b bag) Len() int { return len(b.certs) } 67 68 // Less implements sort.Sort(data Interface) for bag. 69 func (b bag) Less(i, j int) bool { 70 ci := b.certs[i].Raw 71 cj := b.certs[j].Raw 72 if len(ci) != len(cj) { 73 return len(ci) < len(cj) 74 } 75 for n := range ci { 76 if ci[n] < cj[n] { 77 return true 78 } 79 if ci[n] > cj[n] { 80 return false 81 } 82 } 83 return false 84 } 85 86 // Swap implements sort.Sort(data Interface) for bag. 87 func (b bag) Swap(i, j int) { 88 t := b.certs[i] 89 b.certs[i] = b.certs[j] 90 b.certs[j] = t 91 } 92