Joh*_*Doe 2 php c# encryption cryptography
我有一个在php 7.2上运行的应用程序,需要使用以下条件对字符串进行加密:
我已经知道应该得到的输出,但是我的脚本会返回所有不同的字符串,由于IV(openssl_random_pseude_bytes),我认为我并不能真正理解它的逻辑。我对加密没有足够的经验,因此无法弄清楚。
$string = 'my-string';
$cipher = 'BF-CFB';
$key = 'my-secret-key';
$ivlen = openssl_cipher_iv_length($cipher);
$iv = openssl_random_pseudo_bytes($ivlen);
$encrypted = base64_encode(openssl_encrypt($string, $cipher, $key, OPENSSL_RAW_DATA, $iv));
Run Code Online (Sandbox Code Playgroud)
例
加密的目的是为了访问API,并且提供了用C#编写的加密方法示例。问题是该脚本每次都与我的脚本生成相同的字符串。我必须构建自己的脚本,以便获得与提供的官方示例相同的结果(这是一个代码段:)
public new int Encrypt(
byte[] dataIn,
int posIn,
byte[] dataOut,
int posOut,
int count)
{
int end = posIn + count;
?
byte[] iv = this.iv;
?
int ivBytesLeft = this.ivBytesLeft;
int ivPos = iv.Length - ivBytesLeft;
?
// consume what's left in the IV buffer, but make sure to keep the new
// ciphertext in a round-robin fashion (since it represents the new IV)
if (ivBytesLeft >= count)
{
// what we have is enough to deal with the request
for (; posIn < end; posIn++, posOut++, ivPos++)
{
iv[ivPos] = dataOut[posOut] = (byte)(dataIn[posIn] ^ iv[ivPos]);
}
this.ivBytesLeft = iv.Length - ivPos;
return count;
}
for (; ivPos < BLOCK_SIZE; posIn++, posOut++, ivPos++)
{
iv[ivPos] = dataOut[posOut] = (byte)(dataIn[posIn] ^ iv[ivPos]);
}
count -= ivBytesLeft;
?
uint[] sbox1 = this.sbox1;
uint[] sbox2 = this.sbox2;
uint[] sbox3 = this.sbox3;
uint[] sbox4 = this.sbox4;
?
uint[] pbox = this.pbox;
?
uint pbox00 = pbox[0];
uint pbox01 = pbox[1];
uint pbox02 = pbox[2];
uint pbox03 = pbox[3];
uint pbox04 = pbox[4];
uint pbox05 = pbox[5];
uint pbox06 = pbox[6];
uint pbox07 = pbox[7];
uint pbox08 = pbox[8];
uint pbox09 = pbox[9];
uint pbox10 = pbox[10];
uint pbox11 = pbox[11];
uint pbox12 = pbox[12];
uint pbox13 = pbox[13];
uint pbox14 = pbox[14];
uint pbox15 = pbox[15];
uint pbox16 = pbox[16];
uint pbox17 = pbox[17];
?
// now load the current IV into 32bit integers for speed
uint hi = (((uint)iv[0]) << 24) |
(((uint)iv[1]) << 16) |
(((uint)iv[2]) << 8) |
iv[3];
?
uint lo = (((uint)iv[4]) << 24) |
(((uint)iv[5]) << 16) |
(((uint)iv[6]) << 8) |
iv[7];
?
// we deal with the even part first
int rest = count % BLOCK_SIZE;
end -= rest;
?
for (; ; )
{
// need to create new IV material no matter what
hi ^= pbox00;
lo ^= (((sbox1[(int)(hi >> 24)] + sbox2[(int)((hi >> 16) & 0x0ff)]) ^ sbox3[(int)((hi >> 8) & 0x0ff)]) + sbox4[(int)(hi & 0x0ff)]) ^ pbox01;
hi ^= (((sbox1[(int)(lo >> 24)] + sbox2[(int)((lo >> 16) & 0x0ff)]) ^ sbox3[(int)((lo >> 8) & 0x0ff)]) + sbox4[(int)(lo & 0x0ff)]) ^ pbox02;
lo ^= (((sbox1[(int)(hi >> 24)] + sbox2[(int)((hi >> 16) & 0x0ff)]) ^ sbox3[(int)((hi >> 8) & 0x0ff)]) + sbox4[(int)(hi & 0x0ff)]) ^ pbox03;
hi ^= (((sbox1[(int)(lo >> 24)] + sbox2[(int)((lo >> 16) & 0x0ff)]) ^ sbox3[(int)((lo >> 8) & 0x0ff)]) + sbox4[(int)(lo & 0x0ff)]) ^ pbox04;
lo ^= (((sbox1[(int)(hi >> 24)] + sbox2[(int)((hi >> 16) & 0x0ff)]) ^ sbox3[(int)((hi >> 8) & 0x0ff)]) + sbox4[(int)(hi & 0x0ff)]) ^ pbox05;
hi ^= (((sbox1[(int)(lo >> 24)] + sbox2[(int)((lo >> 16) & 0x0ff)]) ^ sbox3[(int)((lo >> 8) & 0x0ff)]) + sbox4[(int)(lo & 0x0ff)]) ^ pbox06;
lo ^= (((sbox1[(int)(hi >> 24)] + sbox2[(int)((hi >> 16) & 0x0ff)]) ^ sbox3[(int)((hi >> 8) & 0x0ff)]) + sbox4[(int)(hi & 0x0ff)]) ^ pbox07;
hi ^= (((sbox1[(int)(lo >> 24)] + sbox2[(int)((lo >> 16) & 0x0ff)]) ^ sbox3[(int)((lo >> 8) & 0x0ff)]) + sbox4[(int)(lo & 0x0ff)]) ^ pbox08;
lo ^= (((sbox1[(int)(hi >> 24)] + sbox2[(int)((hi >> 16) & 0x0ff)]) ^ sbox3[(int)((hi >> 8) & 0x0ff)]) + sbox4[(int)(hi & 0x0ff)]) ^ pbox09;
hi ^= (((sbox1[(int)(lo >> 24)] + sbox2[(int)((lo >> 16) & 0x0ff)]) ^ sbox3[(int)((lo >> 8) & 0x0ff)]) + sbox4[(int)(lo & 0x0ff)]) ^ pbox10;
lo ^= (((sbox1[(int)(hi >> 24)] + sbox2[(int)((hi >> 16) & 0x0ff)]) ^ sbox3[(int)((hi >> 8) & 0x0ff)]) + sbox4[(int)(hi & 0x0ff)]) ^ pbox11;
hi ^= (((sbox1[(int)(lo >> 24)] + sbox2[(int)((lo >> 16) & 0x0ff)]) ^ sbox3[(int)((lo >> 8) & 0x0ff)]) + sbox4[(int)(lo & 0x0ff)]) ^ pbox12;
lo ^= (((sbox1[(int)(hi >> 24)] + sbox2[(int)((hi >> 16) & 0x0ff)]) ^ sbox3[(int)((hi >> 8) & 0x0ff)]) + sbox4[(int)(hi & 0x0ff)]) ^ pbox13;
hi ^= (((sbox1[(int)(lo >> 24)] + sbox2[(int)((lo >> 16) & 0x0ff)]) ^ sbox3[(int)((lo >> 8) & 0x0ff)]) + sbox4[(int)(lo & 0x0ff)]) ^ pbox14;
lo ^= (((sbox1[(int)(hi >> 24)] + sbox2[(int)((hi >> 16) & 0x0ff)]) ^ sbox3[(int)((hi >> 8) & 0x0ff)]) + sbox4[(int)(hi & 0x0ff)]) ^ pbox15;
hi ^= (((sbox1[(int)(lo >> 24)] + sbox2[(int)((lo >> 16) & 0x0ff)]) ^ sbox3[(int)((lo >> 8) & 0x0ff)]) + sbox4[(int)(lo & 0x0ff)]) ^ pbox16;
?
uint swap = lo ^ pbox17;
lo = hi;
hi = swap;
?
if (posIn >= end)
{
// exit right in the middle so we always have new IV material for the rest below
break;
}
?
hi ^= (((uint)dataIn[posIn]) << 24) |
(((uint)dataIn[posIn + 1]) << 16) |
(((uint)dataIn[posIn + 2]) << 8) |
dataIn[posIn + 3];
?
lo ^= (((uint)dataIn[posIn + 4]) << 24) |
(((uint)dataIn[posIn + 5]) << 16) |
(((uint)dataIn[posIn + 6]) << 8) |
dataIn[posIn + 7];
?
posIn += 8;
?
// now stream out the whole block
dataOut[posOut] = (byte)(hi >> 24);
dataOut[posOut + 1] = (byte)(hi >> 16);
dataOut[posOut + 2] = (byte)(hi >> 8);
dataOut[posOut + 3] = (byte)hi;
?
dataOut[posOut + 4] = (byte)(lo >> 24);
dataOut[posOut + 5] = (byte)(lo >> 16);
dataOut[posOut + 6] = (byte)(lo >> 8);
dataOut[posOut + 7] = (byte)lo;
?
posOut += 8;
}
?
// store back the new IV
iv[0] = (byte)(hi >> 24);
iv[1] = (byte)(hi >> 16);
iv[2] = (byte)(hi >> 8);
iv[3] = (byte)hi;
iv[4] = (byte)(lo >> 24);
iv[5] = (byte)(lo >> 16);
iv[6] = (byte)(lo >> 8);
iv[7] = (byte)lo;
?
// emit the rest
for (int i = 0; i < rest; i++)
{
iv[i] = dataOut[posOut + i] = (byte)(dataIn[posIn + i] ^ iv[i]);
}
?
this.ivBytesLeft = iv.Length - rest;
?
return count;
}
Run Code Online (Sandbox Code Playgroud)
这就是您的PHP代码所期望的。CFB模式将分组密码转换为流密码。由于语义安全性(或随机加密),对于同一密钥下的每种加密,您需要不同的IV。否则,一旦攻击者注意到IV的重复使用,攻击者就可以像一次性垫一样使用两次垫式攻击。
您应该始终重新生成IV。
$iv = openssl_random_pseudo_bytes($ivlen);
Run Code Online (Sandbox Code Playgroud)
注意:仍然存在一个问题,如果密钥使用过多,您可能会为同一密钥两次生成相同的IV。IV重用最简单的缓解方法是使用增量IV或通过使用LFSR生成IV。如果您要更改每种加密的密钥,那么IV重用就不是问题,但是,更改IV比更改密钥更容易。
更新:我已经通过查看注释找到了您的C#源代码
// consume what's left in the IV buffer, but make sure to keep the new
Run Code Online (Sandbox Code Playgroud)
该代码的作者说
/// Useful if you don't want to deal with padding of blocks (in comparsion to CBC), however
/// a safe initialization vector (IV) is still needed.
Run Code Online (Sandbox Code Playgroud)
此代码当前使用不安全。
您可以使用
SetIV(value, 0);
Run Code Online (Sandbox Code Playgroud)
函数value通过使用PHP加密来初始化IV 。
| 归档时间: |
|
| 查看次数: |
215 次 |
| 最近记录: |