我正在将用Python编写的模块转换为Perl6。在模块中,有一个名为create_key的方法,该方法使用os.urandom进行加密:
def create_key(size):
return binascii.hexlify(os.urandom(size))[:16]
该文档将
os.urandom
描述为:在Perl 6中,有一个名为Buf的类,但是没有用于它的随机方法。那么如何使用Perl 6实现
os.urandom(size)
? 最佳答案
您总是可以只使用Python的urandom
sub py-urandom( UInt $size ){
use Inline::Python;
state $py = Inline::Python.new; # reuse the same instance
once $py.import('os'); # load the Python os library only once
$py.call('os','urandom', $size);
}
say py-urandom(10)».fmt('%02X').join; # 1473A7D5455F15D3726B
要使以上各项正常工作,需要安装
python-dev
操作系统软件包。然后使用Inline::Python
安装zef
。您也可以使用
binascii.hexlify
sub create-key ( UInt $size ) {
use Inline::Python;
state $py = Inline::Python.new;
once $py.import('os');
once $py.import('binascii');
$py.call('binascii','hexlify', $py.call('os','urandom',$size)).decode('ascii');
}
我敢肯定有更好的方法可以完成上述操作,但这是我第一次使用
Inline::Python
。 (这很明显,因为我必须安装python-dev
才能回答此问题)从长远来看,另一种可能更好的方法是根据它是在Linux,OpenBSD还是Windows上运行而仅调用
getrandom
,getentropy
或CryptGenRandom
。基本上复制os.urandom
的实现。下面是一个快速编写的示例。
sub urandom ( UInt $size ){
use NativeCall;
my constant is-win = $*DISTRO.is-win;
my constant is-openbsd = $*DISTRO.name eq 'openbsd';
if is-win {
fail "urandom doesn't handle Windows yet";
# It is more involved on Windows, and I don't use Windows
} elsif is-openbsd {
# note that this is untested as I don't use OpenBSD
if $size > 256 {
fail "urandom doesn't handle more than 256 on OpenBSD"
# note that this could be changed to load it in 256 byte chunks
}
sub getentropy( Buf \buf, size_t \buflen --> int32 ) is native {}
my Buf $buf .= allocate($size);
my $result = getentropy( $buf, $size );
fail if $result !== 0;
$buf
} else { # presumably Linux or other UNIX-like
sub getrandom (Buf \buf, size_t \buflen, uint32 \flags --> ssize_t) is native {}
my Buf $buf .= allocate($size);
my $total = getrandom( $buf, $size, 0 );
fail unless $total == $size; # could be changed to call it for the rest
$buf;
}
}
say urandom(10)».fmt('%02X').join; # 0EF9EDB3EBC724C0E9CE
如果您使用的是
/dev/urandom
的系统,则可以直接从中读取。sub urandom ( UInt $size ){
my $urandom will leave {.close}
= '/dev/urandom'.IO.open(:bin,:ro);
$urandom.read( $size )
}
say urandom(10)».fmt('%02X').join; # 01B6C41AD0A77732C328
最好的方法是使用像Crypt::Random这样已经完成上述操作的模块。
它实现了我没有的Windows所需的代码,但是它在* NIX系统上使用了
/dev/urandom
文件。# alias &Crypt::Random::crypt_random_buf as &urandom
my &urandom = do {
use Crypt::Random;
&crypt_random_buf
}
say urandom(10)».fmt('%02X').join; # 841720513678B1811E2D
关于raku - 如何在Perl 6中实现Python的os.urandom方法?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54006977/