...

Source file src/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/mpi.go

Documentation: github.com/ProtonMail/go-crypto/openpgp/internal/encoding

     1  // Copyright 2017 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 encoding
     6  
     7  import (
     8  	"io"
     9  	"math/big"
    10  	"math/bits"
    11  )
    12  
    13  // An MPI is used to store the contents of a big integer, along with the bit
    14  // length that was specified in the original input. This allows the MPI to be
    15  // reserialized exactly.
    16  type MPI struct {
    17  	bytes     []byte
    18  	bitLength uint16
    19  }
    20  
    21  // NewMPI returns a MPI initialized with bytes.
    22  func NewMPI(bytes []byte) *MPI {
    23  	for len(bytes) != 0 && bytes[0] == 0 {
    24  		bytes = bytes[1:]
    25  	}
    26  	if len(bytes) == 0 {
    27  		bitLength := uint16(0)
    28  		return &MPI{bytes, bitLength}
    29  	}
    30  	bitLength := 8*uint16(len(bytes)-1) + uint16(bits.Len8(bytes[0]))
    31  	return &MPI{bytes, bitLength}
    32  }
    33  
    34  // Bytes returns the decoded data.
    35  func (m *MPI) Bytes() []byte {
    36  	return m.bytes
    37  }
    38  
    39  // BitLength is the size in bits of the decoded data.
    40  func (m *MPI) BitLength() uint16 {
    41  	return m.bitLength
    42  }
    43  
    44  // EncodedBytes returns the encoded data.
    45  func (m *MPI) EncodedBytes() []byte {
    46  	return append([]byte{byte(m.bitLength >> 8), byte(m.bitLength)}, m.bytes...)
    47  }
    48  
    49  // EncodedLength is the size in bytes of the encoded data.
    50  func (m *MPI) EncodedLength() uint16 {
    51  	return uint16(2 + len(m.bytes))
    52  }
    53  
    54  // ReadFrom reads into m the next MPI from r.
    55  func (m *MPI) ReadFrom(r io.Reader) (int64, error) {
    56  	var buf [2]byte
    57  	n, err := io.ReadFull(r, buf[0:])
    58  	if err != nil {
    59  		if err == io.EOF {
    60  			err = io.ErrUnexpectedEOF
    61  		}
    62  		return int64(n), err
    63  	}
    64  
    65  	m.bitLength = uint16(buf[0])<<8 | uint16(buf[1])
    66  	m.bytes = make([]byte, (int(m.bitLength)+7)/8)
    67  
    68  	nn, err := io.ReadFull(r, m.bytes)
    69  	if err == io.EOF {
    70  		err = io.ErrUnexpectedEOF
    71  	}
    72  
    73  	// remove leading zero bytes from malformed GnuPG encoded MPIs:
    74  	// https://bugs.gnupg.org/gnupg/issue1853
    75  	// for _, b := range m.bytes {
    76  	// 	if b != 0 {
    77  	// 		break
    78  	// 	}
    79  	// 	m.bytes = m.bytes[1:]
    80  	// 	m.bitLength -= 8
    81  	// }
    82  
    83  	return int64(n) + int64(nn), err
    84  }
    85  
    86  // SetBig initializes m with the bits from n.
    87  func (m *MPI) SetBig(n *big.Int) *MPI {
    88  	m.bytes = n.Bytes()
    89  	m.bitLength = uint16(n.BitLen())
    90  	return m
    91  }
    92  

View as plain text