質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

Q&A

解決済

1回答

1716閲覧

Sha2モジュールとBigintモジュールの使用方法が正しくない

namuyan

総合スコア76

Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

0グッド

0クリップ

投稿2019/02/18 17:15

Rustのチュートリアルを終えたばかりです。rustc 1.34.0-nightly

下記のコードをコンパイルできません。

rust

1use pyo3::prelude::*; 2use pyo3::wrap_pyfunction; 3use pyo3::types::PyBytes; 4use sha2::{Sha256, Sha512, Digest}; 5use byteorder::{LittleEndian, WriteBytesExt}; 6use bigint::U512; 7 8#[pyfunction] 9fn sha256hash_vec(byte: &PyBytes) -> PyResult<Vec<u8>> { 10 let mut hasher = Sha256::new(); 11 hasher.input(byte.as_bytes()); 12 let r = hasher.result().to_vec(); 13 Ok(r) 14} 15 16#[pyfunction] 17fn sha256hash_bytes(_py: Python<'_>, byte: &PyBytes) -> PyResult<Py<PyBytes>> { 18 let mut hasher = Sha256::new(); 19 hasher.input(byte.as_bytes()); 20 let mut r = hasher.result(); 21 Ok(PyBytes::new(_py, &mut r)) 22} 23 24#[inline] 25fn int2byte(int: u32) ->Vec<u8> { 26 let mut wtr = Vec::with_capacity(4); 27 wtr.write_u32::<LittleEndian>(int).unwrap(); 28 wtr 29} 30 31#[inline] 32fn byte2int(byte: &[u8]) -> U512 { 33 U512::from(byte) 34} 35 36#[pyfunction] 37fn hash_generator(_py: Python<'_>, address: &str, nonce: u32) -> Vec<Py<PyBytes>> { 38 let mut hasher = Sha512::new(); 39 // seed [address 40bytes]-[nonce 4bytes] 40 hasher.input(address.as_bytes()); 41 hasher.input(int2byte(nonce)); 42 let mut hashed_ints = Vec::with_capacity(64); 43 for _ in 0..64 { 44 let hash = hasher.result(); 45 hashed_ints.push(byte2int(hash.as_slice())); 46 hasher.input(hash); 47 } 48 let hash = hasher.result(); 49 let final_int = byte2int(hash.as_slice()); 50 let mut hash_bytes = Vec::with_capacity(128); 51 for int in hashed_ints { 52 let int = int ^ final_int; 53 let mut bytes: [u8; 128]; 54 int.to_little_endian(&mut bytes); 55 hash_bytes.push(PyBytes::new(_py, &mut bytes)); 56 } 57 return hash_bytes; 58} 59 60/// This module is a python module implemented in Rust. 61#[pymodule] 62fn pochash(_py: Python, m: &PyModule) -> PyResult<()> { 63 //m.add_wrapped(wrap_pyfunction!(hash_generator))?; 64 Ok(()) 65}

error

1error[E0382]: use of moved value: `hasher` 2 --> src\lib.rs:44:20 3 | 438 | let mut hasher = Sha512::new(); 5 | ---------- move occurs because `hasher` has type `sha2::sha512::Sha512`, which does not implement the `Copy` trait 6... 744 | let hash = hasher.result(); 8 | ^^^^^^ value moved here, in previous iteration of loop 9 10error[E0381]: borrow of possibly uninitialized variable: `bytes` 11 --> src\lib.rs:54:30 12 | 1354 | int.to_little_endian(&mut bytes); 14 | ^^^^^^^^^^ use of possibly uninitialized `bytes` 15 16error: aborting due to 2 previous errors

以下の二点が疑問としてあがりました。

  1. hasher.result()の出力なのですが、GenericArrayの扱い方がよくわかりません。変数が束縛されたはずなのですがMoveされている?
  2. U512をBytesに変換したいのですがやり方がおかしいようです。to_little_endianを使用すると思われるのですがうまくいかず、正しいやり方を教えて下さい。documentより読み取れるようになると嬉しいのですが。

解答の方を宜しくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

hasher.result()の出力なのですが、GenericArrayの扱い方がよくわかりません。変数が束縛されたはずなのですがMoveされている?

rust

1 for _ in 0..64 { 2 let hash = hasher.result(); 3 hashed_ints.push(byte2int(hash.as_slice())); 4 hasher.input(hash); 5 }

forループの中でhasher.result()を繰り返し呼んでますが、このメソッドは以下のようにレシーバとして(&selfではなく)selfをとります。self(つまりhasher)の所有権をとりますので1回しか呼べません。そのためにエラーになっています。

https://docs.rs/sha2/0.8.0/sha2/trait.Digest.html#tymethod.result

fn result(self) -> GenericArray<u8, Self::OutputSize>

Retrieve result and consume hasher instance.
(結果を取り出しhasherのインスタンスを消費する)

clone()hasherを複製して、それに対してresult()を呼んでみてください。こうすれば元のhasherはそのまま残りますのでコンパイルできるようになります。

rust

1 for _ in 0..64 { 2 let hash = hasher.clone().result(); 3 hashed_ints.push(byte2int(hash.as_slice())); 4 hasher.input(hash); 5 }

U512をBytesに変換したいのですがやり方がおかしいようです。to_little_endianを使用すると思われるのですがうまくいかず、正しいやり方を教えて下さい。

rust

1 let mut bytes: [u8; 128]; 2 int.to_little_endian(&mut bytes);

上のコードですとbytesの場所は確保していますが、その内容を初期化していないためにエラーになっています。以下のように初期化すればコンパイルできるようになります。

rust

1 let mut bytes = [0u8; 128]; // u8型の0で初期化する 2 int.to_little_endian(&mut bytes);

ただ、これを実行するとto_little_endian()がpanicしてしまいました。

thread 'main' panicked at 'assertion failed: 8 * 8 == bytes.len()', ...

ドキュメントを読んでないのでよくわかりませんが、多分to_little_endian()bytes[0u8; 128]型ではなくて、[0u8; 64]型であることを期待しているのだと思います。

投稿2019/02/19 00:56

編集2019/02/19 04:13
tatsuya6502

総合スコア2035

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問