XXTEA 加密算法的 JavaScript 和 PHP 实现

时间:2025-04-25 18:00:53
  • <?php
  • /* XXTEA encryption arithmetic library.
  • *
  • * Copyright (C) 2006 Ma Bingyao <andot@>
  • * Version: 1.5
  • * LastModified: Dec 5, 2006
  • * This library is free. You can redistribute it and/or modify it.
  • */
  • function long2str($v, $w) {
  • $len = count($v);
  • $n = ($len - 1) << 2;
  • if ($w) {
  • $m = $v[$len - 1];
  • if (($m < $n - 3) || ($m > $n)) return false;
  • $n = $m;
  • }
  • $s = array();
  • for ($i = 0; $i < $len; $i++) {
  • $s[$i] = pack("V", $v[$i]);
  • }
  • if ($w) {
  • return substr(join('', $s), 0, $n);
  • }
  • else {
  • return join('', $s);
  • }
  • }
  • function str2long($s, $w) {
  • $v = unpack("V*", $s. str_repeat("/0", (4 - strlen($s) % 4) & 3));
  • $v = array_values($v);
  • if ($w) {
  • $v[count($v)] = strlen($s);
  • }
  • return $v;
  • }
  • function int32($n) {
  • while ($n >= 2147483648) $n -= 4294967296;
  • while ($n <= -2147483649) $n += 4294967296;
  • return (int)$n;
  • }
  • function xxtea_encrypt($str, $key) {
  • if ($str == "") {
  • return "";
  • }
  • $v = str2long($str, true);
  • $k = str2long($key, false);
  • if (count($k) < 4) {
  • for ($i = count($k); $i < 4; $i++) {
  • $k[$i] = 0;
  • }
  • }
  • $n = count($v) - 1;
  • $z = $v[$n];
  • $y = $v[0];
  • $delta = 0x9E3779B9;
  • $q = floor(6 + 52 / ($n + 1));
  • $sum = 0;
  • while (0 < $q--) {
  • $sum = int32($sum + $delta);
  • $e = $sum >> 2 & 3;
  • for ($p = 0; $p < $n; $p++) {
  • $y = $v[$p + 1];
  • $mx = int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z));
  • $z = $v[$p] = int32($v[$p] + $mx);
  • }
  • $y = $v[0];
  • $mx = int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z));
  • $z = $v[$n] = int32($v[$n] + $mx);
  • }
  • return long2str($v, false);
  • }
  • function xxtea_decrypt($str, $key) {
  • if ($str == "") {
  • return "";
  • }
  • $v = str2long($str, false);
  • $k = str2long($key, false);
  • if (count($k) < 4) {
  • for ($i = count($k); $i < 4; $i++) {
  • $k[$i] = 0;
  • }
  • }
  • $n = count($v) - 1;
  • $z = $v[$n];
  • $y = $v[0];
  • $delta = 0x9E3779B9;
  • $q = floor(6 + 52 / ($n + 1));
  • $sum = int32($q * $delta);
  • while ($sum != 0) {
  • $e = $sum >> 2 & 3;
  • for ($p = $n; $p > 0; $p--) {
  • $z = $v[$p - 1];
  • $mx = int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z));
  • $y = $v[$p] = int32($v[$p] - $mx);
  • }
  • $z = $v[$n];
  • $mx = int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z));
  • $y = $v[0] = int32($v[0] - $mx);
  • $sum = int32($sum - $delta);
  • }
  • return long2str($v, true);
  • }
  • ?>