• 締切済み

mcryptで英数字(12未満)のみにする方法

指定した文字をmycryptを使って12文字未満の英数字に暗号化したいのですが、 記号など含まれず、英数字のみに暗号化するにはどのようなコードを書けばよいのでしょうか? コードを書いて頂けると助かります。 宜しくお願い致します。

みんなの回答

回答No.4

> 平文が5の倍数の文字数でない場合に、謎文字列を追加したものが返ってくる件なのですが、 > 残り文字の計算の仕方がわからないので、正規表現で数字のみを返すようにしようと思うのですが、 > この謎文字に数字が含まれることってありますかね? くっつく謎文字列は何が入ることもありえるので、正規表現で数字か調べるのはあまり役に立たないと思います。Base32エンコードは5バイトのデータを8文字で表現したものなので、Base32エンコードするとデータの長さは8/5倍、デコードすると5/8倍になります。つまり、12文字の暗号化+Base32エンコードされた文字を復号すると、floor(12 * 5 / 8)バイトのデータが出てきます。これを元にsubstrすれば良いかもしれません。 暗号化という要望だったので単純に暗号化しましたが、このコードには改ざんをチェックするコードが一切ついていないので、実用する場合は元のデータのSHA256などのハッシュ値 (あるいはその一部) を元のデータに追加して、復号後にチェックしたほうがいいです。ECBモードやCBCモードではないので、一部の文字列の改ざんは他に伝搬せず、改ざんがあっても復号された文字からはわかりません。もちろん、復号された値が数字かチェックするという方法も10/256回試すと当たるのであまり役に立ちません。 http://okwave.jp/qa/q7476282.html のようなことを考えているなら1~10000までの数字はこちらの#2さんの回答にあるとおり2バイトで表現できるので、自分だったら2バイトでIDを表現したものに4バイトのハッシュ値を付けます。 コードに書くとこんな感じです。(Base32の不具合を治すコードも入れたつもりです。) 改ざんを検出すると、数字の代わりに-1を返します。 $number = '12345'; $key = "This is a key."; $salt = "This is a salt."; $c = new NumberCodec($key, $iv); $cipher_text = $c->encode($number); print $cipher_text."\n"; print strlen($cipher_text)."\n"; print $c->decode($cipher_text,0)."\n"; print $c->decode(substr($cipher_text,1))."\n"; /** * Number Encoder/Decoder. * Encoded string will have digital signature, and encrypted. * The digital signature will be verified at decode time. * * @package default * @author Hanabutako. */ class NumberCodec { function __construct($password, $salt) { $this->my_crypt = new MyCrypt($password, $salt); } /** * Encode a given number. * * @param $number number to be encoded. * @return base32 encoded encrypted string with digital signature. */ function encode($number) { $number_hex = sprintf("%x", intval($number)); if (strlen($number_hex) % 2 != 0) { $number_hex = "0$number_hex"; } $number_hexbin = hex2bin($number_hex); $digest = substr(hex2bin(hash('sha256', $number_hexbin)), 0, 4); return $this->my_crypt->encrypt($digest . $number_hexbin); } /** * Decode from a given string. * * @param $encrypted_string encrypted string. * @return number if verify suceeded. Otherwise, -1. */ function decode($encrypted_string) { $decoded_length = floor(strlen($encrypted_string) * 5 / 8); $decrypted = substr($this->my_crypt->decrypt($encrypted_string), 0, $decoded_length); $digest = substr($decrypted, 0, 4); $hexbin = substr($decrypted, 4); if (substr(hex2bin(hash('sha256', $hexbin)), 0, 4) != $digest) { return -1; } return intval(bin2hex($hexbin), 16); } }

全文を見る
すると、全ての回答が全文表示されます。
回答No.3

元の平文が8文字未満なら、CTRモード、OFBモード、あるいはCFBモードで暗号化して、Base32でエンコードすればよいと思います。 実際のコードはこんな感じです。 $plain = 'abcdefg'; $key = "This is a key."; $salt = "This is a salt."; $c = new MyCrypt($key, $iv); print $c->encrypt($plain) . "\n"; print strlen($c->encrypt($plain)) . "\n"; print $c->decrypt($c->encrypt($plain)) . "\n"; /** * Encrypt/Decrypt string. * Encrypted value is encoded with Base32. * * package default * author Hanabutako. */ class MyCrypt { function __construct($password, $salt) { $this->base32 = new Base32(); $this->td = mcrypt_module_open('rijndael-256', '', 'ctr', ''); $key_size = mcrypt_enc_get_key_size($this->td); $iv_size = mcrypt_enc_get_iv_size($this->td); $this->key = str_hash_pbkdf2($password, $salt, 10, $key_size, 'sha256'); $this->iv = str_hash_pbkdf2($password, $salt, 10, $iv_size, 'sha256', 32); } function __destruct() { mcrypt_module_close($this->td); } /** * Encrypt the given plain text. * * @return base32 encoded encrypted string. */ function encrypt($plain) { mcrypt_generic_init($this->td, $this->key, $this->iv); $encrypted = mcrypt_generic($this->td, $plain); mcrypt_generic_deinit($this->td); return $this->base32->encode($encrypted, $padding=false); } /** * Decrypt the given cipher text encoded with Base32. * * @return decrypted plain text. */ function decrypt($encrypted) { $decoded = $this->base32->decode($encrypted); mcrypt_generic_init($this->td, $this->key, $this->iv); $plain = mdecrypt_generic($this->td, $decoded); mcrypt_generic_deinit($this->td); return $plain; } } 文字数オーバーしたのでライブラリーは省略しています。 Base32のライブラリーはここから調達して、不具合があったので手直ししました。 http://php.net/manual/en/function.base-convert.php このライブラリーは8文字にアラインされていない場合の扱いが雑なので、その部分を調整する必要があります。この不具合のために平文が5の倍数の文字数でない場合に、謎文字列を追加したものがかえってきます。decode処理で残り文字列を計算して、残り文字列以上書かせない様にすれば治ります。 PBKDF2のライブラリーはここから調達しました。 http://php.net/manual/ja/function.hash-hmac.php まぁ、実装の一例ということで。

people900
質問者

お礼

回答ありがとうございます。 とても参考になりました!助かりました(^^) 平文が5の倍数の文字数でない場合に、謎文字列を追加したものが返ってくる件なのですが、 残り文字の計算の仕方がわからないので、正規表現で数字のみを返すようにしようと思うのですが、この謎文字に数字が含まれることってありますかね?

全文を見る
すると、全ての回答が全文表示されます。
  • osamuy
  • ベストアンサー率42% (1231/2878)
回答No.2

英字大小+数字=56種が12文字で、71.45ビットを表現できるから、ブロック長が64ビットの暗号を使えばよいかと。 www.php.netのMCryptリファレンスに使用例がありますので、そちらを読んでみては。 ただ、本来の目的が http://okwave.jp/qa/q7476282.html > ユーザーIDが1~10000まであるとするとそれぞれのIDを8文字の英数字に暗号化したくなった場合 ――にあるのだとしたら、そもそもユーザIDを暗号化する必然性がないし、暗号化するならば英数12文字以下なんて制約をつけるのはちょっとアレかもと思えたり。

people900
質問者

お礼

回答ありがとうございます。 ユーザーIDを暗号化する必然性は状況次第であり得ます。 理由はここでは割愛します。

全文を見る
すると、全ての回答が全文表示されます。
  • shimix
  • ベストアンサー率54% (865/1590)
回答No.1

復号可能な暗号化という条件ですよね?「指定した文字」の長さと文字種はどういう条件でしょうか。暗号化する以上、元の文字数より長くなることはあっても短くはなりません。 mcryptで利用可能な暗号化形式で(元の文字列長が短くても)英数字のみで12文字未満ってありましたっけ?記号を含むどころかバイナリが生成される形式はたくさんありますが・・・。さすがに「全部試してみた」という方も少ないとは思います。ご自身では「試してみよう」というおつもりはないのでしょうかね。

people900
質問者

お礼

回答ありがとうございました。忙しくて調べる時間がなかったためこちらで質問しようと思いました。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 暗号化文字列を英数字のみにしたい

    文字列をJavaで暗号化してURLのクエリストリングに付加したいのですが、「=」「+」等の記号が含まれるとURLエンコーディングしないといけません。 こちらの都合上それを防ぎたいので、暗号化後の文字列を半角英数字のみで構成されるようにしたいのです。 いい案があればご教授ください。 尚、現在はアルゴリズムBlowfishで暗号化したバイト配列をBase64方式にてエンコードしています。 それですと記号が含まれてしまいます。

    • ベストアンサー
    • Java
  • 数字を8文字の英数字にハッシュ化

    例えば会員制のサイトの会員数が10000で ユーザーIDが1~10000まであるとすると それぞれのIDを8文字の英数字に暗号化したくなった場合、どの関数を使用すれば良いでしょうか? md5だと復号化できないし長すぎるので、 復号化でき文字数も指定できる方法を、ご教示いただけると幸いです。 宜しくお願い致します。

    • ベストアンサー
    • PHP
  • 半角英数字を大文字に変換する方法、初心者です。

    HPの設定の過程で英数字の小文字と大文字で出来たパスワードを入れるようになってます。 半角小文字はキーボード左上の「半角/全角 漢字」を押せば入ってると思うんですが (注:記号を打ち込んでも***の記号で表示されるため分からないのです) 英数字を半角大文字に変換するのはどのようにしたらよいのでしょうか? 打ち込んで記号、英数字を表示されるのであれば出来るんですが…  質問の内容が少し分かりづらいかもしれませんが宜しくお願いします。

  • 全角文字列から英数字のみ抜き出す方法は?

    Perl 文字コード sjis 以下のように、全角文字列の中から、全角英数字のみを抜き出したいのですが、良い方法はありますでしょうか。 あア亜ABC-123 ↓ ABC-123 宜しくお願い致します。

    • ベストアンサー
    • Perl
  • なぜ英数字を半角にする人が多いのか?(なぜ英数字以外の記号は半角にしないのか?)

    ネット上を見てると、英数字……取り分け数字は、 どんな場合でも(1桁でも2桁でも関係なく)半角にしている人が多いように思えます。 これはなぜでしょうか? 「それは昔からの決まりだから。」と聞いたことがあるのですが、 そういう人の中には、僕が思うに英数字を半角にしているだけで、 「!」「?」「#」「&」など、カタカナ以外の半角にできる記号を、半角にしていない人がいるんです。 これっておかしいと思います。 おそらく英数字を半角にするのが昔からの決まりだったのは、 昔のパソコンを使っていた人の多くが1バイト文字を使っていたからでしょうし……。 それなら、カタカナは別として、英数字だけでなく、他のすべての記号を半角入力するべきだと思います。 英数字だけ半角なんて、絶対中途半端だし、変です。 「英数字だけ半角にするのに、他の記号は半角にしない理由。」 回答お待ちしております。

  • 英数字を並べて大きな英数字を表す(アスキーアートの様な)

    タイトルの通り、大きな文字で表したい英数字そのものを並べて 大きな英数字を表す事をなんて呼ぶのでしょうか? これも「アスキーアート」と呼ぶのでしょうか? 例えば、英字の「E」を大きな「E」で表したい時 EEEEEEEEEEEE EE EEEEEEEEEEEE EE EEEEEEEEEEEE 「H」の場合 HH        HH HH        HH HH        HH HHHHHHHHHHHH HH        HH HH        HH HH        HH の様に、そのものの英字を使ってそのものの英字を大きく 見せる、というもの。 詳しい情報、Webページをご存知の方、お教え願います。 英数字(大文字小文字に数字 26*2+10=62文字文)全てを 集めたいと思っています。「#」や「%」の様な記号もあれば ベストなんですが。 1つ1つこつこつと作れない事もないのですが、簡単に収集 できればと思ったのですが、何せまず呼び名も名称も分からない ので、検索するのもあぐねている状態で。 よろしくお願いします。

  • 英数字と記号の正規表現

    英数字と記号の文字であればtrueを返すような判定を正規表現で行いたいです。 英数字の判定([0-9a-zA-Z])、記号([\\p{Punct}]+)の判定は個別にテストして動作したのですが、二つを組み合わせて書くようにするにはどのようにすればよいのでしょうか? 当然ですが、以下のように書くと文字列の全てがそれぞれ記号なのか、英数字なのかを判定してしまうためfalseを返してしまいます。 String str = "~!@#$%^&*()_+{}|:"<>?`-=[]\;',./1234567890abcdefgxyz"; System.out.println(str.matches("[\\p{Punct}]+") || str.matches("[0-9a-zA-Z]+")); 以上、宜しくお願いします。

    • ベストアンサー
    • Java
  • phpのコードで暗号化された文字列を得る方法

    WordPressの無料で配布されているテンプレートの footer.phpにはこのようなコードが書かれています。 _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ <? eval(gzinflate(base64_decode('暗号化された文字列'))); ?> _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ 文字列には英数字が沢山並んでいますが、これを暗号化される前の状態にしたいです。 どうすれば良いでしょうかご教示お願いします。

    • 締切済み
    • PHP
  • 暗号化・復号化のアルゴリズムにはどんなものがありますか?

    Cでプログラミングを勉強しており、20文字ほどの文字列を暗号化・復号化するプログラムを考えていますが、ネットを検索しても暗号化アルゴリズムでなかなかいいものが見つかりません。 私のリクエストとしては ・暗号化対象は半角英数字、半角記号のみ。 ・単に文字コードを1つずつずらしたような簡単な暗号ではなく、複雑なアルゴリズムを使用したい。 ・アルゴリズムは複雑でもプログラムは簡潔にできるものがいい。(長くても数百行程度)。 ・アルゴリズム自体の仕様が公開されている。 ・アルゴリズムは数学式で表せるものがいい。 ・スーパーコンピュータを使わなければ解けないほど時間がかかる暗号化アルゴリズムでなくてもいい。 ・暗号化のライブラリファイルは使わず、自前で全部コードを書きたい。 ・公開鍵や秘密鍵を使わなくてもいい。 上記の条件を満たす暗号化アルゴリズムでいいものがありましたら、教えてください。 以上、よろしくお願いします。

  • 全角英数字のみ半角英数字にするには。

    VisualC++6.00 を使用しています。 ダイアログのエディットボックスで入力された文字を、 全角英数字のみ半角英数字にしたいのですが、 LCMapString だと、カタカナも半角になってしまいます。 英数字のみ半角にするには、どのようにすればいいでしょうか。 よろしくお願いします。