Golang:将字节数组转换为big.Int

Golang:将字节数组转换为big.Int

问题描述:

I'm trying to create an RSA Public Key from a Modulus and Exponent stored in a byte array. After some experimentation I've got the following:

func bytes_to_int(b []byte) (acc uint64) {
  length := len(b)
  if length % 4 != 0 {
    extra := (4 - length % 4)
    b = append([]byte(strings.Repeat("\000", extra)), b...)
    length += extra
  }
  var block uint32
  for i := 0; i < length; i += 4 {
    block = binary.BigEndian.Uint32(b[i:i+4])
    acc = (acc << 32) + uint64(block)
  }
return
}

func main() {
  fmt.Println(bytes_to_int(data[:128]))
  fmt.Println(bytes_to_int(data[128:]))
}

This appears to work (although I'm not convinced there isn't a better way). My next step was to convert it to use math/big in order to handle larger numbers. I can see an Lsh function to do the << but can't figure out how to recursively add the Uint32(block) to the big.Int.

For reference, the Public Key I'm attempting to import is a Mixmaster Key stored in a keyring (pubring.mix): http://www.mixmin.net/draft-sassaman-mixmaster-XX.html#key-format http://pinger.mixmin.net/pubring.mix

You want Int.SetBytes to make a big.int from a slice of []byte.

func (z *Int) SetBytes(buf []byte) *Int

SetBytes interprets buf as the bytes of a big-endian unsigned integer, sets z to that value, and returns z.

This should be quite straightforward to use in your application since your keys are in big-endian format according to the doc you linked.

Like Nick mentioned, you could use SetBytes, keep in mind the input is in base64 so you have to decode that first.

Example:

func Base64ToInt(s string) (*big.Int, error) {
    data, err := base64.StdEncoding.DecodeString(s)
    if err != nil {
        return nil, err
    }
    i := new(big.Int)
    i.SetBytes(data)
    return i, nil
}

import "math/big"

z := new(big.Int)
z.SetBytes(byteSliceHere)