This commit is contained in:
Mino 2020-03-19 15:48:42 +09:00
parent a0c0fe9faf
commit c7bdd01b52
2 changed files with 23 additions and 19 deletions

View file

@ -5,14 +5,13 @@ using System.Runtime.CompilerServices;
namespace Dalamud.Bootstrap.Crypto namespace Dalamud.Bootstrap.Crypto
{ {
/// <summary> /// <summary>
/// A class that implements Blowfish algorithm. /// A class that implements Blowfish (with ECB block mode of operation; see remarks.) algorithm.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// Sole purpose of this class is that to produce the value barely enough to be compatible with the algorithm seen in FINAL FANTASY XIV: A Relam Reborn. /// Sole purpose of this class is that to produce the value **barely** enough to be compatible with the algorithm seen in FINAL FANTASY XIV: A Relam Reborn.
/// Therefore, codes are not audited by security experts nor I don't believe that this is a correct implementation. /// Therefore, codes are not audited by security experts nor I don't believe that this is a correct implementation.
/// Heck, it even uses ECB block cipher mode! (because that's what FFXIV uses)
/// ///
/// Please, don't try to use this in production. /// Please, don't even use this in production.
/// </remarks> /// </remarks>
internal sealed class Blowfish internal sealed class Blowfish
{ {
@ -59,8 +58,17 @@ namespace Dalamud.Bootstrap.Crypto
{ {
CheckBuffer(source, destination); CheckBuffer(source, destination);
// TODO: this is shit unsafe
throw new NotImplementedException(); {
fixed (byte* pSrc = source)
fixed (byte* pDst = destination)
{
for (var offset = 0; offset < source.Length; offset += 8)
{
EncryptBlock(pSrc + offset, pDst + offset);
}
}
}
} }
/// <summary> /// <summary>
@ -84,10 +92,9 @@ namespace Dalamud.Bootstrap.Crypto
fixed (byte* pSrc = source) fixed (byte* pSrc = source)
fixed (byte* pDst = destination) fixed (byte* pDst = destination)
{ {
ref var a = source.[4]; for (var offset = 0; offset < source.Length; offset += 8)
for (byte* it = pDst; it < pDst + buffer.Length; it += 8)
{ {
DecryptBlock(it, it); DecryptBlock(pSrc + offset, pDst + offset);
} }
} }
} }
@ -125,11 +132,8 @@ namespace Dalamud.Bootstrap.Crypto
private unsafe void EncryptBlock(byte* input, byte* output) private unsafe void EncryptBlock(byte* input, byte* output)
{ {
var inputBlock = (uint*)input; var xl = Unsafe.ReadUnaligned<uint>(input);
var outputBlock = (uint*)output; var xr = Unsafe.ReadUnaligned<uint>(input + 4);
var xl = UinputBlock[0];
var xr = inputBlock[1];
// will be elided by JIT // will be elided by JIT
if (!BitConverter.IsLittleEndian) if (!BitConverter.IsLittleEndian)
@ -147,15 +151,15 @@ namespace Dalamud.Bootstrap.Crypto
xr = BinaryPrimitives.ReverseEndianness(xr); xr = BinaryPrimitives.ReverseEndianness(xr);
} }
outputBlock[0] = xl; Unsafe.WriteUnaligned(output, xl);
outputBlock[1] = xr; Unsafe.WriteUnaligned(output + 4, xr);
} }
/// <summary> /// <summary>
/// Decrypts a block /// Decrypts a block
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// `input` and `output` are assumed to be unaligned to 4 bytes. (left and right part of the block) /// `input` and `output` are assumed to be not aligned.
/// </remarks> /// </remarks>
private unsafe void DecryptBlock(byte* input, byte* output) private unsafe void DecryptBlock(byte* input, byte* output)
{ {

View file

@ -69,6 +69,7 @@ namespace Dalamud.Bootstrap.SqexArg
Span<byte> keyBytes = stackalloc byte[8]; Span<byte> keyBytes = stackalloc byte[8];
var keyCandicate = keyFragment; var keyCandicate = keyFragment;
while (true) while (true)
{ {
if (!CreateKey(keyBytes, keyCandicate)) if (!CreateKey(keyBytes, keyCandicate))
@ -78,8 +79,7 @@ namespace Dalamud.Bootstrap.SqexArg
} }
var blowfish = new Blowfish(keyBytes); var blowfish = new Blowfish(keyBytes);
blowfish.DecryptInPlace();
if (/* if data looks valid, return blowfish */) if (/* if data looks valid, return blowfish */)
{ {
// ... // ...