auparse/hex.go (85 lines of code) (raw):

// Licensed to Elasticsearch B.V. under one or more contributor // license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright // ownership. Elasticsearch B.V. licenses this file to you under // the Apache License, Version 2.0 (the "License"); you may // not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. package auparse import ( "bytes" "encoding/hex" "errors" "fmt" "net" "strconv" "strings" "github.com/elastic/go-libaudit/v2/internal" ) const nullTerminator = "\x00" func hexToString(h string) (string, error) { output, err := decodeUppercaseHexString(h) if err != nil { return "", err } nullTerm := bytes.Index(output, []byte(nullTerminator)) if nullTerm != -1 { output = output[:nullTerm] } return internal.UnsafeByteSlice2String(output), nil } func hexToStrings(h string) ([]string, error) { output, err := decodeUppercaseHexString(h) if err != nil { return nil, err } return strings.Split(string(output), nullTerminator), nil } func hexToDec(h string) (int32, error) { num, err := strconv.ParseInt(h, 16, 32) return int32(num), err } func hexToIP(h string) (string, error) { if len(h) == 8 { a1, _ := hexToDec(h[0:2]) a2, _ := hexToDec(h[2:4]) a3, _ := hexToDec(h[4:6]) a4, _ := hexToDec(h[6:8]) return fmt.Sprintf("%d.%d.%d.%d", a1, a2, a3, a4), nil } else if len(h) == 32 { b, err := hex.DecodeString(h) if err != nil { return "", err } return net.IP(b).String(), nil } return "", errors.New("invalid size") } // decodeUppercaseHex decodes src into hex.DecodedLen(len(src)) bytes, // returning the actual number of bytes written to dst. // // Decode expects that src contain only hexadecimal // characters and that src should have an even length. func decodeUppercaseHex(dst, src []byte) (int, error) { if len(src)%2 == 1 { return 0, hex.ErrLength } for i := 0; i < len(src)/2; i++ { a, ok := fromHexChar(src[i*2]) if !ok { return 0, hex.InvalidByteError(src[i*2]) } b, ok := fromHexChar(src[i*2+1]) if !ok { return 0, hex.InvalidByteError(src[i*2+1]) } dst[i] = (a << 4) | b } return len(src) / 2, nil } // fromHexChar converts a hex character into its value and a success flag. func fromHexChar(c byte) (byte, bool) { switch { case '0' <= c && c <= '9': return c - '0', true case 'A' <= c && c <= 'F': return c - 'A' + 10, true } return 0, false } // decodeUppercaseHexString returns the bytes represented by the hexadecimal // string s. func decodeUppercaseHexString(s string) ([]byte, error) { src := []byte(s) dst := make([]byte, hex.DecodedLen(len(src))) _, err := decodeUppercaseHex(dst, src) if err != nil { return nil, err } return dst, nil }