github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/xcrypto/pkcs12/bmp-string.go (about)

     1  // Copyright 2015 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package pkcs12
     6  
     7  import (
     8  	"errors"
     9  	"unicode/utf16"
    10  )
    11  
    12  // bmpString returns s encoded in UCS-2 with a zero terminator.
    13  func bmpString(s string) ([]byte, error) {
    14  	// References:
    15  	// https://tools.ietf.org/html/rfc7292#appendix-B.1
    16  	// https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane
    17  	//  - non-BMP characters are encoded in UTF 16 by using a surrogate pair of 16-bit codes
    18  	//	  EncodeRune returns 0xfffd if the rune does not need special encoding
    19  	//  - the above RFC provides the info that BMPStrings are NULL terminated.
    20  
    21  	ret := make([]byte, 0, 2*len(s)+2)
    22  
    23  	for _, r := range s {
    24  		if t, _ := utf16.EncodeRune(r); t != 0xfffd {
    25  			return nil, errors.New("pkcs12: string contains characters that cannot be encoded in UCS-2")
    26  		}
    27  		ret = append(ret, byte(r/256), byte(r%256))
    28  	}
    29  
    30  	return append(ret, 0, 0), nil
    31  }
    32  
    33  func decodeBMPString(bmpString []byte) (string, error) {
    34  	if len(bmpString)%2 != 0 {
    35  		return "", errors.New("pkcs12: odd-length BMP string")
    36  	}
    37  
    38  	// strip terminator if present
    39  	if l := len(bmpString); l >= 2 && bmpString[l-1] == 0 && bmpString[l-2] == 0 {
    40  		bmpString = bmpString[:l-2]
    41  	}
    42  
    43  	s := make([]uint16, 0, len(bmpString)/2)
    44  	for len(bmpString) > 0 {
    45  		s = append(s, uint16(bmpString[0])<<8+uint16(bmpString[1]))
    46  		bmpString = bmpString[2:]
    47  	}
    48  
    49  	return string(utf16.Decode(s)), nil
    50  }