Add functions for canonicalizing an RDNSequence
This commit is contained in:
parent
a6c74b6009
commit
02b6c5ee51
|
@ -0,0 +1,92 @@
|
|||
// Copyright (C) 2019 Opsmate, Inc.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License, v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// This software is distributed WITHOUT A WARRANTY OF ANY KIND.
|
||||
// See the Mozilla Public License for details.
|
||||
|
||||
package certspotter
|
||||
|
||||
import (
|
||||
"encoding/asn1"
|
||||
)
|
||||
|
||||
func canonicalizeRDNString(fromStr string) string {
|
||||
from := []byte(fromStr)
|
||||
to := []byte{}
|
||||
inWhitespace := true
|
||||
for _, ch := range from {
|
||||
if ch == ' ' || ch == '\f' || ch == '\n' || ch == '\r' || ch == '\t' || ch == '\v' {
|
||||
if !inWhitespace {
|
||||
to = append(to, ' ')
|
||||
}
|
||||
inWhitespace = true
|
||||
} else {
|
||||
if ch >= 'A' && ch <= 'Z' {
|
||||
to = append(to, ch+32) // convert to lowercase
|
||||
} else {
|
||||
to = append(to, ch)
|
||||
}
|
||||
inWhitespace = false
|
||||
}
|
||||
}
|
||||
if inWhitespace && len(to) > 0 {
|
||||
// whack off the space character that we appended
|
||||
to = to[:len(to)-1]
|
||||
}
|
||||
return string(to)
|
||||
}
|
||||
|
||||
func shouldCanonicalizeASN1String(value *asn1.RawValue) bool {
|
||||
if !value.IsCompound && value.Class == 0 {
|
||||
return value.Tag == 12 || value.Tag == 19 || value.Tag == 22 || value.Tag == 20 || value.Tag == 26 || value.Tag == 30 || value.Tag == 28
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func canonicalizeATV(oldATV AttributeTypeAndValue) (AttributeTypeAndValue, error) {
|
||||
if shouldCanonicalizeASN1String(&oldATV.Value) {
|
||||
str, err := decodeASN1String(&oldATV.Value)
|
||||
if err != nil {
|
||||
return AttributeTypeAndValue{}, err
|
||||
}
|
||||
str = canonicalizeRDNString(str)
|
||||
return AttributeTypeAndValue{
|
||||
Type: oldATV.Type,
|
||||
Value: asn1.RawValue{
|
||||
Class: 0,
|
||||
Tag: asn1.TagUTF8String,
|
||||
IsCompound: false,
|
||||
Bytes: []byte(str),
|
||||
},
|
||||
}, nil
|
||||
} else {
|
||||
return oldATV, nil
|
||||
}
|
||||
}
|
||||
|
||||
func canonicalizeRDNSet(oldSet RelativeDistinguishedNameSET) (RelativeDistinguishedNameSET, error) {
|
||||
newSet := make([]AttributeTypeAndValue, len(oldSet))
|
||||
for i := range oldSet {
|
||||
var err error
|
||||
newSet[i], err = canonicalizeATV(oldSet[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return newSet, nil
|
||||
}
|
||||
|
||||
func CanonicalizeRDNSequence(oldSequence RDNSequence) (RDNSequence, error) {
|
||||
newSequence := make([]RelativeDistinguishedNameSET, len(oldSequence))
|
||||
for i := range oldSequence {
|
||||
var err error
|
||||
newSequence[i], err = canonicalizeRDNSet(oldSequence[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return newSequence, nil
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
// Copyright (C) 2019 Opsmate, Inc.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License, v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// This software is distributed WITHOUT A WARRANTY OF ANY KIND.
|
||||
// See the Mozilla Public License for details.
|
||||
|
||||
package certspotter
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
type stringCanonTest struct {
|
||||
in string
|
||||
out string
|
||||
}
|
||||
|
||||
var stringCanonTests = []stringCanonTest{
|
||||
{"", ""},
|
||||
{" ", ""},
|
||||
{" ", ""},
|
||||
{"abc", "abc"},
|
||||
{"aBc", "abc"},
|
||||
{"ab c", "ab c"},
|
||||
{"ab c", "ab c"},
|
||||
{"ab\n c", "ab c"},
|
||||
{" ab c ", "ab c"},
|
||||
{" ab c ", "ab c"},
|
||||
{" ab c", "ab c"},
|
||||
{"ab c ", "ab c"},
|
||||
{"abc ", "abc"},
|
||||
{"abc ", "abc"},
|
||||
{" abc ", "abc"},
|
||||
{" abc ", "abc"},
|
||||
{" abc", "abc"},
|
||||
{" aBc de f g\n", "abc de f g"},
|
||||
}
|
||||
|
||||
func TestCanonicalizeRDNString(t *testing.T) {
|
||||
for i, test := range stringCanonTests {
|
||||
ret := canonicalizeRDNString(test.in)
|
||||
if test.out != ret {
|
||||
t.Errorf("#%d: canonicalizeRDNString(%q) = %q, want %q", i, test.in, ret, test.out)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue