英文:
Put the last 8 bits of a big.Int into a uint8
问题
我正在尝试编写一个密码生成器。它要求字符以ASCII表示,但我想使用crypto/rand
。然而,它提供的是big.Int
格式的数字,我需要将相关的低8位转换为可在字符串中使用的形式。我尝试过将big.Int
转换为uint8
,但迄今为止没有成功。
有没有一个好的简单方法来做到这一点?我看到一些答案涉及使用encoding/binary
将int64
转换为[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.Int
和rand.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))
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论