はじめに
PHP の GMP 拡張モジュールは、多倍長整数(任意精度の大きな整数)を扱うための強力なツールです。この中でも特に gmp_export
関数は、GMP オブジェクトをバイナリデータに変換するための重要な関数です。今回は、この関数の使い方と実践的な活用法について詳しく解説します。
gmp_export 関数とは?
gmp_export
関数は、GMP オブジェクト(多倍長整数)をバイナリ文字列に変換します。これにより、GMP の大きな整数をコンパクトなバイナリ形式で保存したり転送したりすることが可能になります。
基本的な構文
gmp_export(GMP $gmpnumber, int $word_size = 1, int $options = GMP_MSW_FIRST | GMP_NATIVE_ENDIAN): string
$gmpnumber
: 変換する GMP オブジェクト$word_size
: ワードサイズ(オプション、デフォルトは1)$options
: エンディアンとワード順序のオプション(オプション)- 戻り値: バイナリデータを含む文字列
パラメータの詳細
word_size(ワードサイズ)
ワードサイズは、バイナリデータの各ワードのバイト数を指定します。デフォルトは1(1バイト)ですが、2、4、8などの値も指定できます。
options(オプション)
オプションパラメータには、以下の定数を組み合わせて指定できます:
- ワード順序:
GMP_MSW_FIRST
: 最上位ワードから(デフォルト)GMP_LSW_FIRST
: 最下位ワードから
- バイト順序(エンディアン):
GMP_NATIVE_ENDIAN
: システムのネイティブエンディアン(デフォルト)GMP_BIG_ENDIAN
: ビッグエンディアンGMP_LITTLE_ENDIAN
: リトルエンディアン
複数のオプションを組み合わせる場合はビット OR 演算子 |
で連結します。
使用例
基本的な使い方
<?php
// 数値 123456789 を GMP オブジェクトに変換
$number = gmp_init("123456789");
// デフォルト設定でバイナリエクスポート(ワードサイズ 1)
$binary = gmp_export($number);
// 結果を確認(バイナリなのでbin2hex で16進数表示)
echo "バイナリデータ(16進数): " . bin2hex($binary) . "\n";
echo "バイナリデータ長: " . strlen($binary) . " バイト\n";
// 出力例:
// バイナリデータ(16進数): 075bcd15
// バイナリデータ長: 4 バイト
?>
ワードサイズとエンディアンを指定する例
<?php
$number = gmp_init("123456789");
// ワードサイズ 2 でエクスポート(ビッグエンディアン)
$binary_be = gmp_export($number, 2, GMP_MSW_FIRST | GMP_BIG_ENDIAN);
echo "ビッグエンディアン(16進数): " . bin2hex($binary_be) . "\n";
// ワードサイズ 2 でエクスポート(リトルエンディアン)
$binary_le = gmp_export($number, 2, GMP_MSW_FIRST | GMP_LITTLE_ENDIAN);
echo "リトルエンディアン(16進数): " . bin2hex($binary_le) . "\n";
// 出力例:
// ビッグエンディアン(16進数): 075bcd15
// リトルエンディアン(16進数): 5b07cd15
?>
非常に大きな数値をエクスポートする例
<?php
// 非常に大きな数値
$large_number = gmp_init("123456789012345678901234567890");
// 異なるワードサイズでエクスポート
$binary1 = gmp_export($large_number, 1); // 1バイトワード
$binary4 = gmp_export($large_number, 4); // 4バイトワード
$binary8 = gmp_export($large_number, 8); // 8バイトワード
echo "1バイトワード(16進数): " . bin2hex($binary1) . "\n";
echo "4バイトワード(16進数): " . bin2hex($binary4) . "\n";
echo "8バイトワード(16進数): " . bin2hex($binary8) . "\n";
echo "1バイトワードサイズ: " . strlen($binary1) . " バイト\n";
echo "4バイトワードサイズ: " . strlen($binary4) . " バイト\n";
echo "8バイトワードサイズ: " . strlen($binary8) . " バイト\n";
?>
実践的な活用例
データベースへの保存
大きな整数をコンパクトに保存する場合:
<?php
// 非常に大きな数値(例:暗号鍵など)
$large_number = gmp_init("987654321098765432109876543210987654321");
// バイナリ形式に変換
$binary_data = gmp_export($large_number);
// データベースに保存(例)
$db = new PDO('mysql:host=localhost;dbname=testdb', 'username', 'password');
$stmt = $db->prepare("INSERT INTO large_numbers (number_data) VALUES (?)");
$stmt->execute([$binary_data]);
echo "データベースに保存しました。データサイズ: " . strlen($binary_data) . " バイト";
?>
暗号関連の利用
RSA などの暗号化で使用される大きな整数のやり取り:
<?php
// 暗号キーを想定した大きな素数
$prime = gmp_nextprime(gmp_init("10000000000000000000000000000000000000000"));
// バイナリ形式に変換(ビッグエンディアン)
$binary_key = gmp_export($prime, 4, GMP_MSW_FIRST | GMP_BIG_ENDIAN);
// 転送または保存(ここではBase64エンコード)
$encoded_key = base64_encode($binary_key);
echo "エンコードされたキー: " . $encoded_key . "\n";
// 受信側でデコード
$received_binary = base64_decode($encoded_key);
$received_prime = gmp_import($received_binary, 4, GMP_MSW_FIRST | GMP_BIG_ENDIAN);
echo "復元された素数: " . gmp_strval($received_prime);
?>
gmp_import との連携
gmp_export
は gmp_import
関数と対になっており、バイナリデータを GMP オブジェクトに変換する際に使用します:
<?php
$original = gmp_init("12345678901234567890");
echo "元の数値: " . gmp_strval($original) . "\n";
// エクスポート
$binary = gmp_export($original, 4, GMP_MSW_FIRST | GMP_NATIVE_ENDIAN);
echo "バイナリサイズ: " . strlen($binary) . " バイト\n";
// インポート(同じパラメータを使用)
$imported = gmp_import($binary, 4, GMP_MSW_FIRST | GMP_NATIVE_ENDIAN);
echo "インポートした数値: " . gmp_strval($imported) . "\n";
// 元の値と一致するか確認
if (gmp_cmp($original, $imported) === 0) {
echo "成功:値は同一です";
} else {
echo "エラー:値が一致しません";
}
?>
注意点
- パラメータの一致:
gmp_export
とgmp_import
を使用する場合、両方の関数で同じワードサイズとオプションを指定する必要があります。 - 負の数の扱い: GMP は負の数も扱えますが、
gmp_export
は絶対値のみをエクスポートします。負の値を扱う場合は、符号を別途保存する必要があります。 - PHP バージョン: PHP 5.6.1以降で使用可能です。
- メモリ使用量: 非常に大きな数値を扱う場合、メモリ使用量に注意してください。
まとめ
gmp_export
関数は、PHP の GMP 拡張モジュールにおいて、多倍長整数をコンパクトなバイナリ形式に変換するための重要な関数です。大きな整数を効率的に保存、転送したい場合や、暗号関連の処理で多倍長整数を扱う場合に特に役立ちます。
適切なワードサイズとエンディアンオプションを選択することで、様々なシステムや環境との互換性を確保できます。gmp_import
関数と組み合わせることで、多倍長整数の可逆的な変換が可能になり、データの整合性を保ちながら効率的に処理できます。
大規模な数値計算や暗号処理を行うアプリケーションでは、ぜひ gmp_export
関数の活用を検討してみてください。