将big.Int的最后8位放入uint8中

huangapple go评论86阅读模式
英文:

Put the last 8 bits of a big.Int into a uint8

问题

我正在尝试编写一个密码生成器。它要求字符以ASCII表示,但我想使用crypto/rand。然而,它提供的是big.Int格式的数字,我需要将相关的低8位转换为可在字符串中使用的形式。我尝试过将big.Int转换为uint8,但迄今为止没有成功。

有没有一个好的简单方法来做到这一点?我看到一些答案涉及使用encoding/binaryint64转换为[8]uint8,但对于我的目的来说,这些方法似乎过于复杂。任何指导都将不胜感激:)。

英文:

I'm trying to write a password generator. It requires that characters be in ASCII representation, but I'm trying to use crypto/rand. This provides numbers in big.Int format, though, and I need to convert the relevant lower 8 bits to a form usable in a string. I've tried converting from big.Int to uint8 with no luck so far.

Is there a good and easy method to do this? I have seen answers involving using encoding/binary to convert from int64 to [8]uint8, but those seem needlessly complex for my purpose. Any guidance at all would be appreciated :).

答案1

得分: 2

package main

import (
"fmt"
"math/big"
)

func main() {
mpInt := big.NewInt(0x123456789abcdef0)
b := byte(mpInt.Int64())
fmt.Printf("%02x", b)
}


英文:
package main

import (
        "fmt"
        "math/big"
)

func main() {
        mpInt := big.NewInt(0x123456789abcdef0)
        b := byte(mpInt.Int64())
        fmt.Printf("%02x", b)
}

f0

In action: http://play.golang.org/p/92PbLdiVsP


EDIT: Evan Shaw correctly points out in a comment bellow that the above code is actually incorrect for big Ints outside of int64 limits. Instead of pulling it from big.Bytes (which makes a copy of all of the bits representing a big.Int IIRC) it's probably more performant to use big.And:


package main

import (
        "fmt"
        "log"
        "math/big"
)

func lsB(n *big.Int) byte {
        var m big.Int
        return byte(m.And(m.SetInt64(255), n).Int64())
}

func main() {
        var mpInt big.Int
        if _, ok := mpInt.SetString("0x123456789abcdef012342", 0); !ok {
                log.Fatal()
        }

        fmt.Printf("%02x", lsB(&mpInt))
}

Playground: http://play.golang.org/p/pgkGEFgb8-

答案2

得分: 1

如果你想从crypto/rand中获取字节,我建议完全跳过使用big.Intrand.Int(),而是使用rand.Read()rand.Reader

package main

import (
	"crypto/rand"
	"fmt"
	"io"
)

// 如果你只想每次获取一个字节...
// (如果你喜欢,你可以将'byte'改为'int8')
func secureRandomByte() byte {
	data := make([]byte, 1)
	if _, err := rand.Read(data); err != nil {
		// 处理错误
		panic(err)
	}
	return data[0]
}

// 如果你想一次读取多个字节...
func genPassword(len int) (string, error) {
	data := make([]byte, len)
	if _, err := io.ReadFull(rand.Reader, data); err != nil {
		// 处理错误
		return "", err
	}
	for i := range data {
		// XXX 快速转换为可打印字符
		data[i] &= 0x3F
		data[i] += 0x20
	}
	return string(data), nil
}

func main() {
	b := secureRandomByte()
	fmt.Printf("%T = %v\n", b, b)
	fmt.Println(genPassword(16))
}
英文:

If you want to get bytes out of crypto/rand, I'd skip the use of big.Int and rand.Int() entirely and use either rand.Read() or rand.Reader:

package main

import (
	"crypto/rand"
	"fmt"
	"io"
)

// If you want just a byte at a time ...
// (you could change 'byte' to int8 if you prefer)    
func secureRandomByte() byte {
	data := make([]byte, 1)
	if _, err := rand.Read(data); err != nil {
		// handle error
		panic(err)
	}
	return data[0]
}

// If you want to read multiple bytes at a time ...
func genPassword(len int) (string, error) {
	data := make([]byte, len)
	if _, err := io.ReadFull(rand.Reader, data); err != nil {
		// handle error
		return "", err
	}
	for i := range data {
		// XXX quick munge into something printable
		data[i] &= 0x3F
		data[i] += 0x20
	}
	return string(data), nil
}

func main() {
	b := secureRandomByte()
	fmt.Printf("%T = %v\n", b, b)
	fmt.Println(genPassword(16))
}

huangapple
  • 本文由 发表于 2012年9月29日 22:01:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/12653340.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定