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