Move rres
This commit is contained in:
parent
030685212e
commit
3bde422185
9 changed files with 532 additions and 1117 deletions
|
@ -4,6 +4,7 @@ import (
|
||||||
//"bytes"
|
//"bytes"
|
||||||
|
|
||||||
"github.com/gen2brain/raylib-go/raylib"
|
"github.com/gen2brain/raylib-go/raylib"
|
||||||
|
"github.com/gen2brain/raylib-go/rres"
|
||||||
)
|
)
|
||||||
|
|
||||||
const numTextures = 4
|
const numTextures = 4
|
||||||
|
@ -28,15 +29,15 @@ func main() {
|
||||||
//b := MustAsset("data.rres")
|
//b := MustAsset("data.rres")
|
||||||
//reader := bytes.NewReader(b)
|
//reader := bytes.NewReader(b)
|
||||||
|
|
||||||
res := raylib.LoadResource(reader, 0, nil)
|
res := rres.LoadResource(reader, 0, []byte("passwordpassword"))
|
||||||
wav := raylib.LoadWaveEx(res.Data, int32(res.Param1), int32(res.Param2), int32(res.Param3), int32(res.Param4))
|
wav := raylib.LoadWaveEx(res.Data, int32(res.Param1), int32(res.Param2), int32(res.Param3), int32(res.Param4))
|
||||||
snd := raylib.LoadSoundFromWave(wav)
|
snd := raylib.LoadSoundFromWave(wav)
|
||||||
raylib.UnloadWave(wav)
|
raylib.UnloadWave(wav)
|
||||||
|
|
||||||
textures := make([]raylib.Texture2D, numTextures)
|
textures := make([]raylib.Texture2D, numTextures)
|
||||||
for i := 0; i < numTextures; i++ {
|
for i := 0; i < numTextures; i++ {
|
||||||
r := raylib.LoadResource(reader, i+1, nil)
|
r := rres.LoadResource(reader, i+1, []byte("passwordpassword"))
|
||||||
image := raylib.LoadImagePro(r.Data, int32(r.Param1), int32(r.Param2), raylib.TextureFormat(r.Param3))
|
image := raylib.LoadImagePro(r.Data, int32(r.Param1), int32(r.Param2), raylib.PixelFormat(r.Param3))
|
||||||
textures[i] = raylib.LoadTextureFromImage(image)
|
textures[i] = raylib.LoadTextureFromImage(image)
|
||||||
raylib.UnloadImage(image)
|
raylib.UnloadImage(image)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,83 +0,0 @@
|
||||||
package raylib
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/gen2brain/raylib-go/rres"
|
|
||||||
"github.com/gen2brain/raylib-go/rres/rreslib"
|
|
||||||
)
|
|
||||||
|
|
||||||
// LoadResource - Load resource from file by id
|
|
||||||
// NOTE: Returns uncompressed data with parameters, search resource by id
|
|
||||||
func LoadResource(reader io.ReadSeeker, rresID int, key []byte) (data rres.Data) {
|
|
||||||
var fileHeader rres.FileHeader
|
|
||||||
var infoHeader rres.InfoHeader
|
|
||||||
|
|
||||||
reader.Seek(0, 0)
|
|
||||||
|
|
||||||
// Read rres file header
|
|
||||||
err := binary.Read(reader, binary.LittleEndian, &fileHeader)
|
|
||||||
if err != nil {
|
|
||||||
TraceLog(LogWarning, err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify "rRES" identifier
|
|
||||||
if string(fileHeader.ID[:]) != "rRES" {
|
|
||||||
TraceLog(LogWarning, "not a valid raylib resource file")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
reader.Seek(int64(unsafe.Sizeof(fileHeader)), os.SEEK_CUR)
|
|
||||||
|
|
||||||
for i := 0; i < int(fileHeader.Count); i++ {
|
|
||||||
// Read resource info and parameters
|
|
||||||
err = binary.Read(reader, binary.LittleEndian, &infoHeader)
|
|
||||||
if err != nil {
|
|
||||||
TraceLog(LogWarning, err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
reader.Seek(int64(unsafe.Sizeof(infoHeader)), os.SEEK_CUR)
|
|
||||||
|
|
||||||
if int(infoHeader.ID) == rresID {
|
|
||||||
data.Type = uint32(infoHeader.DataType)
|
|
||||||
data.Param1 = infoHeader.Param1
|
|
||||||
data.Param2 = infoHeader.Param2
|
|
||||||
data.Param3 = infoHeader.Param3
|
|
||||||
data.Param4 = infoHeader.Param4
|
|
||||||
|
|
||||||
// Read resource data block
|
|
||||||
b := make([]byte, infoHeader.DataSize)
|
|
||||||
reader.Read(b)
|
|
||||||
|
|
||||||
// Decompress data
|
|
||||||
data.Data, err = rreslib.Decompress(b, int(infoHeader.CompType))
|
|
||||||
if err != nil {
|
|
||||||
TraceLog(LogWarning, "[ID %d] %v", infoHeader.ID, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decrypt data
|
|
||||||
data.Data, err = rreslib.Decrypt(key, data.Data, int(infoHeader.CryptoType))
|
|
||||||
if err != nil {
|
|
||||||
TraceLog(LogWarning, "[ID %d] %v", infoHeader.ID, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if data.Data != nil && len(data.Data) == int(infoHeader.UncompSize) {
|
|
||||||
TraceLog(LogInfo, "[ID %d] Resource data loaded successfully", infoHeader.ID)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Skip required data to read next resource infoHeader
|
|
||||||
reader.Seek(int64(infoHeader.DataSize), os.SEEK_CUR)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if data.Data == nil {
|
|
||||||
TraceLog(LogWarning, "[ID %d] Requested resource could not be found", rresID)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
483
raylib/rres.h
483
raylib/rres.h
|
@ -1,483 +0,0 @@
|
||||||
/**********************************************************************************************
|
|
||||||
*
|
|
||||||
* rres v1.0 - raylib resource (rRES) custom fileformat management functions
|
|
||||||
*
|
|
||||||
* CONFIGURATION:
|
|
||||||
*
|
|
||||||
* #define RREM_IMPLEMENTATION
|
|
||||||
* Generates the implementation of the library into the included file.
|
|
||||||
* If not defined, the library is in header only mode and can be included in other headers
|
|
||||||
* or source files without problems. But only ONE file should hold the implementation.
|
|
||||||
*
|
|
||||||
* DEPENDENCIES:
|
|
||||||
* tinfl - DEFLATE decompression functions
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* LICENSE: zlib/libpng
|
|
||||||
*
|
|
||||||
* Copyright (c) 2016-2017 Ramon Santamaria (@raysan5)
|
|
||||||
*
|
|
||||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
|
||||||
* will the authors be held liable for any damages arising from the use of this software.
|
|
||||||
*
|
|
||||||
* Permission is granted to anyone to use this software for any purpose, including commercial
|
|
||||||
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
|
||||||
*
|
|
||||||
* 1. The origin of this software must not be misrepresented; you must not claim that you
|
|
||||||
* wrote the original software. If you use this software in a product, an acknowledgment
|
|
||||||
* in the product documentation would be appreciated but is not required.
|
|
||||||
*
|
|
||||||
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
|
|
||||||
* as being the original software.
|
|
||||||
*
|
|
||||||
* 3. This notice may not be removed or altered from any source distribution.
|
|
||||||
*
|
|
||||||
**********************************************************************************************/
|
|
||||||
|
|
||||||
/*
|
|
||||||
References:
|
|
||||||
RIFF file-format: http://www.johnloomis.org/cpe102/asgn/asgn1/riff.html
|
|
||||||
ZIP file-format: https://en.wikipedia.org/wiki/Zip_(file_format)
|
|
||||||
http://www.onicos.com/staff/iz/formats/zip.html
|
|
||||||
XNB file-format: http://xbox.create.msdn.com/en-US/sample/xnb_format
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef RRES_H
|
|
||||||
#define RRES_H
|
|
||||||
|
|
||||||
#if !defined(RRES_STANDALONE)
|
|
||||||
#include "raylib.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//#define RRES_STATIC
|
|
||||||
#ifdef RRES_STATIC
|
|
||||||
#define RRESDEF static // Functions just visible to module including this file
|
|
||||||
#else
|
|
||||||
#ifdef __cplusplus
|
|
||||||
#define RRESDEF extern "C" // Functions visible from other files (no name mangling of functions in C++)
|
|
||||||
#else
|
|
||||||
#define RRESDEF extern // Functions visible from other files
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Defines and Macros
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
#define MAX_RESOURCES_SUPPORTED 256
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Types and Structures Definition
|
|
||||||
// NOTE: Some types are required for RAYGUI_STANDALONE usage
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
#if defined(RRES_STANDALONE)
|
|
||||||
// rRES data returned when reading a resource, it contains all required data for user (24 byte)
|
|
||||||
// NOTE: Using void *data pointer, so we can load to image.data, wave.data, mesh.*, (unsigned char *)
|
|
||||||
typedef struct RRESData {
|
|
||||||
unsigned int type; // Resource type (4 byte)
|
|
||||||
|
|
||||||
unsigned int param1; // Resouce parameter 1 (4 byte)
|
|
||||||
unsigned int param2; // Resouce parameter 2 (4 byte)
|
|
||||||
unsigned int param3; // Resouce parameter 3 (4 byte)
|
|
||||||
unsigned int param4; // Resouce parameter 4 (4 byte)
|
|
||||||
|
|
||||||
void *data; // Resource data pointer (4 byte)
|
|
||||||
} RRESData;
|
|
||||||
|
|
||||||
// RRES type (pointer to RRESData array)
|
|
||||||
typedef struct RRESData *RRES; // Resource pointer
|
|
||||||
|
|
||||||
// RRESData type
|
|
||||||
typedef enum {
|
|
||||||
RRES_TYPE_RAW = 0,
|
|
||||||
RRES_TYPE_IMAGE,
|
|
||||||
RRES_TYPE_WAVE,
|
|
||||||
RRES_TYPE_VERTEX,
|
|
||||||
RRES_TYPE_TEXT,
|
|
||||||
RRES_TYPE_FONT_IMAGE,
|
|
||||||
RRES_TYPE_FONT_CHARDATA, // CharInfo { int value, recX, recY, recWidth, recHeight, offsetX, offsetY, xAdvance }
|
|
||||||
RRES_TYPE_DIRECTORY
|
|
||||||
} RRESDataType;
|
|
||||||
|
|
||||||
// Parameters information depending on resource type
|
|
||||||
|
|
||||||
// RRES_TYPE_RAW params: <custom>
|
|
||||||
// RRES_TYPE_IMAGE params: width, height, mipmaps, format
|
|
||||||
// RRES_TYPE_WAVE params: sampleCount, sampleRate, sampleSize, channels
|
|
||||||
// RRES_TYPE_VERTEX params: vertexCount, vertexType, vertexFormat // Use masks instead?
|
|
||||||
// RRES_TYPE_TEXT params: charsCount, cultureCode
|
|
||||||
// RRES_TYPE_FONT_IMAGE params: width, height, format, mipmaps;
|
|
||||||
// RRES_TYPE_FONT_CHARDATA params: charsCount, baseSize
|
|
||||||
// RRES_TYPE_DIRECTORY params: fileCount, directoryCount
|
|
||||||
|
|
||||||
// SpriteFont = RRES_TYPE_FONT_IMAGE chunk + RRES_TYPE_FONT_DATA chunk
|
|
||||||
// Mesh = multiple RRES_TYPE_VERTEX chunks
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Global variables
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
//...
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Module Functions Declaration
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
//RRESDEF RRESData LoadResourceData(const char *rresFileName, int rresId, int part);
|
|
||||||
RRESDEF RRES LoadResource(const char *fileName, int rresId);
|
|
||||||
RRESDEF void UnloadResource(RRES rres);
|
|
||||||
|
|
||||||
/*
|
|
||||||
QUESTION: How to load each type of data from RRES ?
|
|
||||||
|
|
||||||
rres->type == RRES_TYPE_RAW
|
|
||||||
unsigned char data = (unsigned char *)rres[0]->data;
|
|
||||||
|
|
||||||
rres->type == RRES_TYPE_IMAGE
|
|
||||||
Image image;
|
|
||||||
image.data = rres[0]->data; // Be careful, duplicate pointer
|
|
||||||
image.width = rres[0]->param1;
|
|
||||||
image.height = rres[0]->param2;
|
|
||||||
image.mipmaps = rres[0]->param3;
|
|
||||||
image.format = rres[0]->format;
|
|
||||||
|
|
||||||
rres->type == RRES_TYPE_WAVE
|
|
||||||
Wave wave;
|
|
||||||
wave.data = rres[0]->data;
|
|
||||||
wave.sampleCount = rres[0]->param1;
|
|
||||||
wave.sampleRate = rres[0]->param2;
|
|
||||||
wave.sampleSize = rres[0]->param3;
|
|
||||||
wave.channels = rres[0]->param4;
|
|
||||||
|
|
||||||
rres->type == RRES_TYPE_VERTEX (multiple parts)
|
|
||||||
Mesh mesh;
|
|
||||||
mesh.vertexCount = rres[0]->param1;
|
|
||||||
mesh.vertices = (float *)rres[0]->data;
|
|
||||||
mesh.texcoords = (float *)rres[1]->data;
|
|
||||||
mesh.normals = (float *)rres[2]->data;
|
|
||||||
mesh.tangents = (float *)rres[3]->data;
|
|
||||||
mesh.tangents = (unsigned char *)rres[4]->data;
|
|
||||||
|
|
||||||
rres->type == RRES_TYPE_TEXT
|
|
||||||
unsigned char *text = (unsigned char *)rres->data;
|
|
||||||
Shader shader = LoadShaderText(text, rres->param1); Shader LoadShaderText(const char *shdrText, int length);
|
|
||||||
|
|
||||||
rres->type == RRES_TYPE_FONT_IMAGE (multiple parts)
|
|
||||||
rres->type == RRES_TYPE_FONT_CHARDATA
|
|
||||||
SpriteFont font;
|
|
||||||
font.texture = LoadTextureFromImage(image); // rres[0]
|
|
||||||
font.chars = (CharInfo *)rres[1]->data;
|
|
||||||
font.charsCount = rres[1]->param1;
|
|
||||||
font.baseSize = rres[1]->param2;
|
|
||||||
|
|
||||||
rres->type == RRES_TYPE_DIRECTORY
|
|
||||||
unsigned char *fileNames = (unsigned char *)rres[0]->data; // fileNames separed by \n
|
|
||||||
int filesCount = rres[0]->param1;
|
|
||||||
*/
|
|
||||||
|
|
||||||
#endif // RRES_H
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************************
|
|
||||||
*
|
|
||||||
* RRES IMPLEMENTATION
|
|
||||||
*
|
|
||||||
************************************************************************************/
|
|
||||||
|
|
||||||
#if defined(RRES_IMPLEMENTATION)
|
|
||||||
|
|
||||||
#include <stdio.h> // Required for: FILE, fopen(), fclose()
|
|
||||||
|
|
||||||
// Check if custom malloc/free functions defined, if not, using standard ones
|
|
||||||
#if !defined(RRES_MALLOC)
|
|
||||||
#include <stdlib.h> // Required for: malloc(), free()
|
|
||||||
|
|
||||||
#define RRES_MALLOC(size) malloc(size)
|
|
||||||
#define RRES_FREE(ptr) free(ptr)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "external/tinfl.c" // Required for: tinfl_decompress_mem_to_mem()
|
|
||||||
// NOTE: DEFLATE algorythm data decompression
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Defines and Macros
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
//...
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Types and Structures Definition
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// rRES file header (8 byte)
|
|
||||||
typedef struct {
|
|
||||||
char id[4]; // File identifier: rRES (4 byte)
|
|
||||||
unsigned short version; // File version and subversion (2 byte)
|
|
||||||
unsigned short count; // Number of resources in this file (2 byte)
|
|
||||||
} RRESFileHeader;
|
|
||||||
|
|
||||||
// rRES info header, every resource includes this header (16 byte + 16 byte)
|
|
||||||
typedef struct {
|
|
||||||
unsigned int id; // Resource unique identifier (4 byte)
|
|
||||||
unsigned char dataType; // Resource data type (1 byte)
|
|
||||||
unsigned char compType; // Resource data compression type (1 byte)
|
|
||||||
unsigned char cryptoType; // Resource data encryption type (1 byte)
|
|
||||||
unsigned char partsCount; // Resource data parts count, used for splitted data (1 byte)
|
|
||||||
unsigned int dataSize; // Resource data size (compressed or not, only DATA) (4 byte)
|
|
||||||
unsigned int uncompSize; // Resource data size (uncompressed, only DATA) (4 byte)
|
|
||||||
|
|
||||||
unsigned int param1; // Resouce parameter 1 (4 byte)
|
|
||||||
unsigned int param2; // Resouce parameter 2 (4 byte)
|
|
||||||
unsigned int param3; // Resouce parameter 3 (4 byte)
|
|
||||||
unsigned int param4; // Resouce parameter 4 (4 byte)
|
|
||||||
} RRESInfoHeader;
|
|
||||||
|
|
||||||
// Compression types
|
|
||||||
typedef enum {
|
|
||||||
RRES_COMP_NONE = 0, // No data compression
|
|
||||||
RRES_COMP_DEFLATE, // DEFLATE compression
|
|
||||||
RRES_COMP_LZ4, // LZ4 compression
|
|
||||||
RRES_COMP_LZMA, // LZMA compression
|
|
||||||
RRES_COMP_BROTLI, // BROTLI compression
|
|
||||||
// gzip, zopfli, lzo, zstd // Other compression algorythms...
|
|
||||||
} RRESCompressionType;
|
|
||||||
|
|
||||||
// Encryption types
|
|
||||||
typedef enum {
|
|
||||||
RRES_CRYPTO_NONE = 0, // No data encryption
|
|
||||||
RRES_CRYPTO_XOR, // XOR (128 bit) encryption
|
|
||||||
RRES_CRYPTO_AES, // RIJNDAEL (128 bit) encryption (AES)
|
|
||||||
RRES_CRYPTO_TDES, // Triple DES encryption
|
|
||||||
RRES_CRYPTO_BLOWFISH, // BLOWFISH encryption
|
|
||||||
RRES_CRYPTO_XTEA, // XTEA encryption
|
|
||||||
// twofish, RC5, RC6 // Other encryption algorythm...
|
|
||||||
} RRESEncryptionType;
|
|
||||||
|
|
||||||
// Image/Texture data type
|
|
||||||
typedef enum {
|
|
||||||
RRES_IM_UNCOMP_GRAYSCALE = 1, // 8 bit per pixel (no alpha)
|
|
||||||
RRES_IM_UNCOMP_GRAY_ALPHA, // 16 bpp (2 channels)
|
|
||||||
RRES_IM_UNCOMP_R5G6B5, // 16 bpp
|
|
||||||
RRES_IM_UNCOMP_R8G8B8, // 24 bpp
|
|
||||||
RRES_IM_UNCOMP_R5G5B5A1, // 16 bpp (1 bit alpha)
|
|
||||||
RRES_IM_UNCOMP_R4G4B4A4, // 16 bpp (4 bit alpha)
|
|
||||||
RRES_IM_UNCOMP_R8G8B8A8, // 32 bpp
|
|
||||||
RRES_IM_COMP_DXT1_RGB, // 4 bpp (no alpha)
|
|
||||||
RRES_IM_COMP_DXT1_RGBA, // 4 bpp (1 bit alpha)
|
|
||||||
RRES_IM_COMP_DXT3_RGBA, // 8 bpp
|
|
||||||
RRES_IM_COMP_DXT5_RGBA, // 8 bpp
|
|
||||||
RRES_IM_COMP_ETC1_RGB, // 4 bpp
|
|
||||||
RRES_IM_COMP_ETC2_RGB, // 4 bpp
|
|
||||||
RRES_IM_COMP_ETC2_EAC_RGBA, // 8 bpp
|
|
||||||
RRES_IM_COMP_PVRT_RGB, // 4 bpp
|
|
||||||
RRES_IM_COMP_PVRT_RGBA, // 4 bpp
|
|
||||||
RRES_IM_COMP_ASTC_4x4_RGBA, // 8 bpp
|
|
||||||
RRES_IM_COMP_ASTC_8x8_RGBA // 2 bpp
|
|
||||||
//...
|
|
||||||
} RRESImageFormat;
|
|
||||||
|
|
||||||
// Vertex data type
|
|
||||||
typedef enum {
|
|
||||||
RRES_VERT_POSITION,
|
|
||||||
RRES_VERT_TEXCOORD1,
|
|
||||||
RRES_VERT_TEXCOORD2,
|
|
||||||
RRES_VERT_TEXCOORD3,
|
|
||||||
RRES_VERT_TEXCOORD4,
|
|
||||||
RRES_VERT_NORMAL,
|
|
||||||
RRES_VERT_TANGENT,
|
|
||||||
RRES_VERT_COLOR,
|
|
||||||
RRES_VERT_INDEX,
|
|
||||||
//...
|
|
||||||
} RRESVertexType;
|
|
||||||
|
|
||||||
// Vertex data format type
|
|
||||||
typedef enum {
|
|
||||||
RRES_VERT_BYTE,
|
|
||||||
RRES_VERT_SHORT,
|
|
||||||
RRES_VERT_INT,
|
|
||||||
RRES_VERT_HFLOAT,
|
|
||||||
RRES_VERT_FLOAT,
|
|
||||||
//...
|
|
||||||
} RRESVertexFormat;
|
|
||||||
|
|
||||||
#if defined(RRES_STANDALONE)
|
|
||||||
typedef enum { LOG_INFO = 0, LOG_ERROR, LOG_WARNING, LOG_DEBUG, LOG_OTHER } TraceLogType;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Global Variables Definition
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
//...
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Module specific Functions Declaration
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
static void *DecompressData(const unsigned char *data, unsigned long compSize, int uncompSize);
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Module Functions Definition
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Load resource from file by id (could be multiple parts)
|
|
||||||
// NOTE: Returns uncompressed data with parameters, search resource by id
|
|
||||||
RRESDEF RRES LoadResource(const char *fileName, int rresId)
|
|
||||||
{
|
|
||||||
RRES rres = { 0 };
|
|
||||||
|
|
||||||
RRESFileHeader fileHeader;
|
|
||||||
RRESInfoHeader infoHeader;
|
|
||||||
|
|
||||||
FILE *rresFile = fopen(fileName, "rb");
|
|
||||||
|
|
||||||
if (rresFile == NULL) TraceLog(LOG_WARNING, "[%s] rRES raylib resource file could not be opened", fileName);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Read rres file info header
|
|
||||||
fread(&fileHeader.id[0], sizeof(char), 1, rresFile);
|
|
||||||
fread(&fileHeader.id[1], sizeof(char), 1, rresFile);
|
|
||||||
fread(&fileHeader.id[2], sizeof(char), 1, rresFile);
|
|
||||||
fread(&fileHeader.id[3], sizeof(char), 1, rresFile);
|
|
||||||
fread(&fileHeader.version, sizeof(short), 1, rresFile);
|
|
||||||
fread(&fileHeader.count, sizeof(short), 1, rresFile);
|
|
||||||
|
|
||||||
// Verify "rRES" identifier
|
|
||||||
if ((fileHeader.id[0] != 'r') && (fileHeader.id[1] != 'R') && (fileHeader.id[2] != 'E') && (fileHeader.id[3] != 'S'))
|
|
||||||
{
|
|
||||||
TraceLog(LOG_WARNING, "[%s] This is not a valid raylib resource file", fileName);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int i = 0; i < fileHeader.count; i++)
|
|
||||||
{
|
|
||||||
// Read resource info and parameters
|
|
||||||
fread(&infoHeader, sizeof(RRESInfoHeader), 1, rresFile);
|
|
||||||
|
|
||||||
if (infoHeader.id == rresId)
|
|
||||||
{
|
|
||||||
rres = (RRES)malloc(sizeof(RRESData)*infoHeader.partsCount);
|
|
||||||
|
|
||||||
// Load all required resources parts
|
|
||||||
for (int k = 0; k < infoHeader.partsCount; k++)
|
|
||||||
{
|
|
||||||
// TODO: Verify again that rresId is the same in every part
|
|
||||||
|
|
||||||
// Register data type and parameters
|
|
||||||
rres[k].type = infoHeader.dataType;
|
|
||||||
rres[k].param1 = infoHeader.param1;
|
|
||||||
rres[k].param2 = infoHeader.param2;
|
|
||||||
rres[k].param3 = infoHeader.param3;
|
|
||||||
rres[k].param4 = infoHeader.param4;
|
|
||||||
|
|
||||||
// Read resource data block
|
|
||||||
void *data = RRES_MALLOC(infoHeader.dataSize);
|
|
||||||
fread(data, infoHeader.dataSize, 1, rresFile);
|
|
||||||
|
|
||||||
if (infoHeader.compType == RRES_COMP_DEFLATE)
|
|
||||||
{
|
|
||||||
void *uncompData = DecompressData(data, infoHeader.dataSize, infoHeader.uncompSize);
|
|
||||||
|
|
||||||
rres[k].data = uncompData;
|
|
||||||
|
|
||||||
RRES_FREE(data);
|
|
||||||
}
|
|
||||||
else rres[k].data = data;
|
|
||||||
|
|
||||||
if (rres[k].data != NULL) TraceLog(LOG_INFO, "[%s][ID %i] Resource data loaded successfully", fileName, (int)infoHeader.id);
|
|
||||||
|
|
||||||
// Read next part
|
|
||||||
fread(&infoHeader, sizeof(RRESInfoHeader), 1, rresFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Skip required data to read next resource infoHeader
|
|
||||||
fseek(rresFile, infoHeader.dataSize, SEEK_CUR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rres[0].data == NULL) TraceLog(LOG_WARNING, "[%s][ID %i] Requested resource could not be found", fileName, (int)rresId);
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(rresFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
return rres;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unload resource data
|
|
||||||
RRESDEF void UnloadResource(RRES rres)
|
|
||||||
{
|
|
||||||
// TODO: When you load resource... how many parts conform it? depends on type? --> Not clear...
|
|
||||||
|
|
||||||
if (rres[0].data != NULL) free(rres[0].data);
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
// Module specific Functions Definition
|
|
||||||
//----------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Data decompression function
|
|
||||||
// NOTE: Allocated data MUST be freed by user
|
|
||||||
static void *DecompressData(const unsigned char *data, unsigned long compSize, int uncompSize)
|
|
||||||
{
|
|
||||||
int tempUncompSize;
|
|
||||||
void *uncompData;
|
|
||||||
|
|
||||||
// Allocate buffer to hold decompressed data
|
|
||||||
uncompData = (mz_uint8 *)RRES_MALLOC((size_t)uncompSize);
|
|
||||||
|
|
||||||
// Check correct memory allocation
|
|
||||||
if (uncompData == NULL)
|
|
||||||
{
|
|
||||||
TraceLog(LOG_WARNING, "Out of memory while decompressing data");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Decompress data
|
|
||||||
tempUncompSize = tinfl_decompress_mem_to_mem(uncompData, (size_t)uncompSize, data, compSize, 1);
|
|
||||||
|
|
||||||
if (tempUncompSize == -1)
|
|
||||||
{
|
|
||||||
TraceLog(LOG_WARNING, "Data decompression failed");
|
|
||||||
RRES_FREE(uncompData);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uncompSize != (int)tempUncompSize)
|
|
||||||
{
|
|
||||||
TraceLog(LOG_WARNING, "Expected uncompressed size do not match, data may be corrupted");
|
|
||||||
TraceLog(LOG_WARNING, " -- Expected uncompressed size: %i", uncompSize);
|
|
||||||
TraceLog(LOG_WARNING, " -- Returned uncompressed size: %i", tempUncompSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
TraceLog(LOG_INFO, "Data decompressed successfully from %u bytes to %u bytes", (mz_uint32)compSize, (mz_uint32)tempUncompSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
return uncompData;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Some required functions for rres standalone module version
|
|
||||||
#if defined(RRES_STANDALONE)
|
|
||||||
// Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG)
|
|
||||||
void TraceLog(int logType, const char *text, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
va_start(args, text);
|
|
||||||
|
|
||||||
switch (msgType)
|
|
||||||
{
|
|
||||||
case LOG_INFO: fprintf(stdout, "INFO: "); break;
|
|
||||||
case LOG_ERROR: fprintf(stdout, "ERROR: "); break;
|
|
||||||
case LOG_WARNING: fprintf(stdout, "WARNING: "); break;
|
|
||||||
case LOG_DEBUG: fprintf(stdout, "DEBUG: "); break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
|
|
||||||
vfprintf(stdout, text, args);
|
|
||||||
fprintf(stdout, "\n");
|
|
||||||
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
if (msgType == LOG_ERROR) exit(1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // RRES_IMPLEMENTATION
|
|
|
@ -30,7 +30,6 @@ import (
|
||||||
"github.com/moutend/go-wav"
|
"github.com/moutend/go-wav"
|
||||||
|
|
||||||
"github.com/gen2brain/raylib-go/rres"
|
"github.com/gen2brain/raylib-go/rres"
|
||||||
"github.com/gen2brain/raylib-go/rres/rreslib"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -156,7 +155,7 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encryption
|
// Encryption
|
||||||
data, err = rreslib.Encrypt([]byte(*key), data, int(infoHeader.CryptoType))
|
data, err = rres.Encrypt([]byte(*key), data, int(infoHeader.CryptoType))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("%v\n", err)
|
fmt.Printf("%v\n", err)
|
||||||
}
|
}
|
||||||
|
@ -164,7 +163,7 @@ func main() {
|
||||||
infoHeader.UncompSize = uint32(len(data))
|
infoHeader.UncompSize = uint32(len(data))
|
||||||
|
|
||||||
// Compression
|
// Compression
|
||||||
data, err = rreslib.Compress(data, int(infoHeader.CompType))
|
data, err = rres.Compress(data, int(infoHeader.CompType))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("%v\n", err)
|
fmt.Printf("%v\n", err)
|
||||||
}
|
}
|
||||||
|
|
526
rres/rres.go
526
rres/rres.go
|
@ -1,5 +1,30 @@
|
||||||
package rres
|
package rres
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/aes"
|
||||||
|
"crypto/cipher"
|
||||||
|
"crypto/des"
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/dsnet/compress/bzip2"
|
||||||
|
"github.com/golang/snappy"
|
||||||
|
"github.com/klauspost/compress/flate"
|
||||||
|
"github.com/pierrec/lz4"
|
||||||
|
xor "github.com/rootlch/encrypt"
|
||||||
|
"github.com/ulikunitz/xz"
|
||||||
|
"golang.org/x/crypto/blowfish"
|
||||||
|
"golang.org/x/crypto/xtea"
|
||||||
|
|
||||||
|
"github.com/gen2brain/raylib-go/raylib"
|
||||||
|
)
|
||||||
|
|
||||||
type Data struct {
|
type Data struct {
|
||||||
// Resource type (4 byte)
|
// Resource type (4 byte)
|
||||||
Type uint32
|
Type uint32
|
||||||
|
@ -163,3 +188,504 @@ const (
|
||||||
VertHfloat
|
VertHfloat
|
||||||
VertFloat
|
VertFloat
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// LoadResource - Load resource from file by id
|
||||||
|
// NOTE: Returns uncompressed data with parameters, search resource by id
|
||||||
|
func LoadResource(reader io.ReadSeeker, rresID int, key []byte) (data Data) {
|
||||||
|
var fileHeader FileHeader
|
||||||
|
var infoHeader InfoHeader
|
||||||
|
|
||||||
|
reader.Seek(0, 0)
|
||||||
|
|
||||||
|
// Read rres file header
|
||||||
|
err := binary.Read(reader, binary.LittleEndian, &fileHeader)
|
||||||
|
if err != nil {
|
||||||
|
raylib.TraceLog(raylib.LogWarning, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify "rRES" identifier
|
||||||
|
if string(fileHeader.ID[:]) != "rRES" {
|
||||||
|
raylib.TraceLog(raylib.LogWarning, "not a valid raylib resource file")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.Seek(int64(unsafe.Sizeof(fileHeader)), os.SEEK_CUR)
|
||||||
|
|
||||||
|
for i := 0; i < int(fileHeader.Count); i++ {
|
||||||
|
// Read resource info and parameters
|
||||||
|
err = binary.Read(reader, binary.LittleEndian, &infoHeader)
|
||||||
|
if err != nil {
|
||||||
|
raylib.TraceLog(raylib.LogWarning, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.Seek(int64(unsafe.Sizeof(infoHeader)), os.SEEK_CUR)
|
||||||
|
|
||||||
|
if int(infoHeader.ID) == rresID {
|
||||||
|
data.Type = uint32(infoHeader.DataType)
|
||||||
|
data.Param1 = infoHeader.Param1
|
||||||
|
data.Param2 = infoHeader.Param2
|
||||||
|
data.Param3 = infoHeader.Param3
|
||||||
|
data.Param4 = infoHeader.Param4
|
||||||
|
|
||||||
|
// Read resource data block
|
||||||
|
b := make([]byte, infoHeader.DataSize)
|
||||||
|
reader.Read(b)
|
||||||
|
|
||||||
|
// Decompress data
|
||||||
|
data.Data, err = Decompress(b, int(infoHeader.CompType))
|
||||||
|
if err != nil {
|
||||||
|
raylib.TraceLog(raylib.LogWarning, "[ID %d] %v", infoHeader.ID, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrypt data
|
||||||
|
data.Data, err = Decrypt(key, data.Data, int(infoHeader.CryptoType))
|
||||||
|
if err != nil {
|
||||||
|
raylib.TraceLog(raylib.LogWarning, "[ID %d] %v", infoHeader.ID, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.Data != nil && len(data.Data) == int(infoHeader.UncompSize) {
|
||||||
|
raylib.TraceLog(raylib.LogInfo, "[ID %d] Resource data loaded successfully", infoHeader.ID)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Skip required data to read next resource infoHeader
|
||||||
|
reader.Seek(int64(infoHeader.DataSize), os.SEEK_CUR)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.Data == nil {
|
||||||
|
raylib.TraceLog(raylib.LogWarning, "[ID %d] Requested resource could not be found", rresID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encrypt data
|
||||||
|
func Encrypt(key, data []byte, cryptoType int) ([]byte, error) {
|
||||||
|
switch cryptoType {
|
||||||
|
case CryptoXOR:
|
||||||
|
c, err := xor.NewXor(string(key))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Encode(data), nil
|
||||||
|
case CryptoAES:
|
||||||
|
b, err := encryptAES(key, data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return b, nil
|
||||||
|
case Crypto3DES:
|
||||||
|
b, err := encrypt3DES(key, data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return b, nil
|
||||||
|
case CryptoBlowfish:
|
||||||
|
b, err := encryptBlowfish(key, data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return b, nil
|
||||||
|
case CryptoXTEA:
|
||||||
|
b, err := encryptXTEA(key, data)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("%v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return b, nil
|
||||||
|
default:
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrypt data
|
||||||
|
func Decrypt(key, data []byte, cryptoType int) ([]byte, error) {
|
||||||
|
switch cryptoType {
|
||||||
|
case CryptoXOR:
|
||||||
|
c, err := xor.NewXor(string(key))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
b := c.Encode(data)
|
||||||
|
return b, nil
|
||||||
|
case CryptoAES:
|
||||||
|
b, err := decryptAES(key, data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return b, nil
|
||||||
|
case Crypto3DES:
|
||||||
|
b, err := decrypt3DES(key, data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return b, nil
|
||||||
|
case CryptoBlowfish:
|
||||||
|
b, err := decryptBlowfish(key, data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return b, nil
|
||||||
|
case CryptoXTEA:
|
||||||
|
b, err := decryptXTEA(key, data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return b, nil
|
||||||
|
default:
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compress data
|
||||||
|
func Compress(data []byte, compType int) ([]byte, error) {
|
||||||
|
switch compType {
|
||||||
|
case CompNone:
|
||||||
|
return data, nil
|
||||||
|
case CompDeflate:
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
|
||||||
|
w, err := flate.NewWriter(buf, flate.DefaultCompression)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = w.Write(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Close()
|
||||||
|
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
case CompLZ4:
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
|
||||||
|
w := lz4.NewWriter(buf)
|
||||||
|
|
||||||
|
_, err := w.Write(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Close()
|
||||||
|
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
case CompLZMA2:
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
|
||||||
|
w, err := xz.NewWriter(buf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = w.Write(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Close()
|
||||||
|
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
case CompBZIP2:
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
|
||||||
|
w, err := bzip2.NewWriter(buf, &bzip2.WriterConfig{Level: bzip2.BestCompression})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = w.Write(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Close()
|
||||||
|
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
case CompSnappy:
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
|
||||||
|
w := snappy.NewWriter(buf)
|
||||||
|
|
||||||
|
_, err := w.Write(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Close()
|
||||||
|
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
default:
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decompress data
|
||||||
|
func Decompress(data []byte, compType int) ([]byte, error) {
|
||||||
|
switch compType {
|
||||||
|
case CompNone:
|
||||||
|
return data, nil
|
||||||
|
case CompDeflate:
|
||||||
|
r := flate.NewReader(bytes.NewReader(data))
|
||||||
|
|
||||||
|
u, err := ioutil.ReadAll(r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Close()
|
||||||
|
|
||||||
|
return u, nil
|
||||||
|
case CompLZ4:
|
||||||
|
r := lz4.NewReader(bytes.NewReader(data))
|
||||||
|
|
||||||
|
u, err := ioutil.ReadAll(r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return u, nil
|
||||||
|
case CompLZMA2:
|
||||||
|
r, err := xz.NewReader(bytes.NewReader(data))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
u, err := ioutil.ReadAll(r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return u, nil
|
||||||
|
case CompBZIP2:
|
||||||
|
r, err := bzip2.NewReader(bytes.NewReader(data), &bzip2.ReaderConfig{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
u, err := ioutil.ReadAll(r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return u, nil
|
||||||
|
case CompSnappy:
|
||||||
|
r := snappy.NewReader(bytes.NewReader(data))
|
||||||
|
|
||||||
|
u, err := ioutil.ReadAll(r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return u, nil
|
||||||
|
default:
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pad to block size
|
||||||
|
func pad(src []byte, blockSize int) []byte {
|
||||||
|
padding := blockSize - len(src)%blockSize
|
||||||
|
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
|
||||||
|
return append(src, padtext...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// unpad
|
||||||
|
func unpad(src []byte) ([]byte, error) {
|
||||||
|
length := len(src)
|
||||||
|
unpadding := int(src[length-1])
|
||||||
|
|
||||||
|
if unpadding > length {
|
||||||
|
return nil, fmt.Errorf("unpad error. This can happen when incorrect encryption key is used.")
|
||||||
|
}
|
||||||
|
|
||||||
|
return src[:(length - unpadding)], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// encryptAES
|
||||||
|
func encryptAES(key, text []byte) ([]byte, error) {
|
||||||
|
block, err := aes.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := pad(text, aes.BlockSize)
|
||||||
|
ciphertext := make([]byte, aes.BlockSize+len(msg))
|
||||||
|
iv := ciphertext[:aes.BlockSize]
|
||||||
|
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cfb := cipher.NewCFBEncrypter(block, iv)
|
||||||
|
cfb.XORKeyStream(ciphertext[aes.BlockSize:], msg)
|
||||||
|
|
||||||
|
return ciphertext, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// decryptAES
|
||||||
|
func decryptAES(key, text []byte) ([]byte, error) {
|
||||||
|
block, err := aes.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len(text) % aes.BlockSize) != 0 {
|
||||||
|
return nil, fmt.Errorf("blocksize must be multiple of decoded message length")
|
||||||
|
}
|
||||||
|
|
||||||
|
iv := text[:aes.BlockSize]
|
||||||
|
msg := text[aes.BlockSize:]
|
||||||
|
|
||||||
|
cfb := cipher.NewCFBDecrypter(block, iv)
|
||||||
|
cfb.XORKeyStream(msg, msg)
|
||||||
|
|
||||||
|
unpadMsg, err := unpad(msg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return unpadMsg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// encrypt3DES
|
||||||
|
func encrypt3DES(key, text []byte) ([]byte, error) {
|
||||||
|
block, err := des.NewTripleDESCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := pad(text, des.BlockSize)
|
||||||
|
ciphertext := make([]byte, des.BlockSize+len(msg))
|
||||||
|
iv := ciphertext[:des.BlockSize]
|
||||||
|
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cbc := cipher.NewCBCEncrypter(block, iv)
|
||||||
|
cbc.CryptBlocks(ciphertext[des.BlockSize:], msg)
|
||||||
|
|
||||||
|
return ciphertext, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// decrypt3DES
|
||||||
|
func decrypt3DES(key, text []byte) ([]byte, error) {
|
||||||
|
block, err := des.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len(text) % des.BlockSize) != 0 {
|
||||||
|
return nil, fmt.Errorf("blocksize must be multiple of decoded message length")
|
||||||
|
}
|
||||||
|
|
||||||
|
iv := text[:des.BlockSize]
|
||||||
|
msg := text[des.BlockSize:]
|
||||||
|
|
||||||
|
cbc := cipher.NewCBCDecrypter(block, iv)
|
||||||
|
cbc.CryptBlocks(msg, msg)
|
||||||
|
|
||||||
|
unpadMsg, err := unpad(msg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return unpadMsg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// encryptBlowfish
|
||||||
|
func encryptBlowfish(key, text []byte) ([]byte, error) {
|
||||||
|
block, err := blowfish.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := pad(text, blowfish.BlockSize)
|
||||||
|
ciphertext := make([]byte, blowfish.BlockSize+len(msg))
|
||||||
|
iv := ciphertext[:blowfish.BlockSize]
|
||||||
|
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cbc := cipher.NewCBCEncrypter(block, iv)
|
||||||
|
cbc.CryptBlocks(ciphertext[blowfish.BlockSize:], msg)
|
||||||
|
|
||||||
|
return ciphertext, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// decryptBlowfish
|
||||||
|
func decryptBlowfish(key, text []byte) ([]byte, error) {
|
||||||
|
block, err := blowfish.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len(text) % blowfish.BlockSize) != 0 {
|
||||||
|
return nil, fmt.Errorf("blocksize must be multiple of decoded message length")
|
||||||
|
}
|
||||||
|
|
||||||
|
iv := text[:blowfish.BlockSize]
|
||||||
|
msg := text[blowfish.BlockSize:]
|
||||||
|
|
||||||
|
cbc := cipher.NewCBCDecrypter(block, iv)
|
||||||
|
cbc.CryptBlocks(msg, msg)
|
||||||
|
|
||||||
|
unpadMsg, err := unpad(msg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return unpadMsg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// encryptXTEA
|
||||||
|
func encryptXTEA(key, text []byte) ([]byte, error) {
|
||||||
|
block, err := xtea.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := pad(text, xtea.BlockSize)
|
||||||
|
ciphertext := make([]byte, xtea.BlockSize+len(msg))
|
||||||
|
iv := ciphertext[:xtea.BlockSize]
|
||||||
|
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cbc := cipher.NewCBCEncrypter(block, iv)
|
||||||
|
cbc.CryptBlocks(ciphertext[xtea.BlockSize:], msg)
|
||||||
|
|
||||||
|
return ciphertext, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// decryptXTEA
|
||||||
|
func decryptXTEA(key, text []byte) ([]byte, error) {
|
||||||
|
block, err := xtea.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len(text) % xtea.BlockSize) != 0 {
|
||||||
|
return nil, fmt.Errorf("blocksize must be multiple of decoded message length")
|
||||||
|
}
|
||||||
|
|
||||||
|
iv := text[:xtea.BlockSize]
|
||||||
|
msg := text[xtea.BlockSize:]
|
||||||
|
|
||||||
|
cbc := cipher.NewCBCDecrypter(block, iv)
|
||||||
|
cbc.CryptBlocks(msg, msg)
|
||||||
|
|
||||||
|
unpadMsg, err := unpad(msg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return unpadMsg, nil
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
all: build
|
|
||||||
|
|
||||||
build:
|
|
||||||
go build -buildmode=c-archive -o rreslib.a
|
|
|
@ -1,18 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
CHROOT="/usr/x86_64-pc-linux-gnu-static"
|
|
||||||
MINGW="/usr/i686-w64-mingw32"
|
|
||||||
RPI="/usr/armv6j-hardfloat-linux-gnueabi"
|
|
||||||
ANDROID="/opt/android-toolchain-arm7"
|
|
||||||
|
|
||||||
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -buildmode=c-archive -o release/linux/rreslib.a -ldflags "-s -w"
|
|
||||||
|
|
||||||
CC="i686-w64-mingw32-gcc" CXX="i686-w64-mingw32-g++" \
|
|
||||||
CGO_ENABLED=1 GOOS=windows GOARCH=386 go build -buildmode=c-archive -o release/win32/rreslib.a -ldflags "-s -w"
|
|
||||||
|
|
||||||
CC="armv6j-hardfloat-linux-gnueabi-gcc" CXX="armv6j-hardfloat-linux-gnueabi-g++" \
|
|
||||||
CGO_ENABLED=1 GOOS=linux GOARCH=arm go build -buildmode=c-archive -o release/rpi/rreslib.a -ldflags "-s -w"
|
|
||||||
|
|
||||||
PATH="$PATH:$ANDROID/bin" \
|
|
||||||
CC="arm-linux-androideabi-gcc" CXX="arm-linux-androideabi-g++" \
|
|
||||||
CGO_ENABLED=1 GOOS=android GOARCH=arm go build -buildmode=c-shared -o release/android/armeabi-v7a/rreslib.so -ldflags "-s -w"
|
|
|
@ -1,69 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/gen2brain/raylib-go/rres/rreslib"
|
|
||||||
)
|
|
||||||
|
|
||||||
//export Compress
|
|
||||||
func Compress(compType C.int, data *C.uchar, uncompSize C.ulong, outCompSize *C.ulong) *C.uchar {
|
|
||||||
d := C.GoBytes(unsafe.Pointer(data), C.int(uncompSize))
|
|
||||||
|
|
||||||
c, err := rreslib.Compress(d, int(compType))
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
*outCompSize = C.ulong(len(c))
|
|
||||||
return (*C.uchar)(unsafe.Pointer(&c[0]))
|
|
||||||
}
|
|
||||||
|
|
||||||
//export Decompress
|
|
||||||
func Decompress(compType C.int, data *C.uchar, uncompSize C.ulong, compSize C.ulong) *C.uchar {
|
|
||||||
d := C.GoBytes(unsafe.Pointer(data), C.int(compSize))
|
|
||||||
|
|
||||||
c, err := rreslib.Decompress(d, int(compType))
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(c) != int(uncompSize) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return (*C.uchar)(unsafe.Pointer(&c[0]))
|
|
||||||
}
|
|
||||||
|
|
||||||
//export Encrypt
|
|
||||||
func Encrypt(cryptoType C.int, key *C.char, data *C.uchar, dataSize C.ulong, outDataSize *C.ulong) *C.uchar {
|
|
||||||
k := []byte(C.GoString(key))
|
|
||||||
d := C.GoBytes(unsafe.Pointer(data), C.int(dataSize))
|
|
||||||
|
|
||||||
c, err := rreslib.Encrypt(k, d, int(cryptoType))
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
*outDataSize = C.ulong(len(c))
|
|
||||||
return (*C.uchar)(unsafe.Pointer(&c[0]))
|
|
||||||
}
|
|
||||||
|
|
||||||
//export Decrypt
|
|
||||||
func Decrypt(cryptoType C.int, key *C.char, data *C.uchar, dataSize C.ulong) *C.uchar {
|
|
||||||
k := []byte(C.GoString(key))
|
|
||||||
d := C.GoBytes(unsafe.Pointer(data), C.int(dataSize))
|
|
||||||
|
|
||||||
c, err := rreslib.Decrypt(k, d, int(cryptoType))
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return (*C.uchar)(unsafe.Pointer(&c[0]))
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need the main() so we can compile as C library
|
|
||||||
func main() {
|
|
||||||
}
|
|
|
@ -1,454 +0,0 @@
|
||||||
// Package rreslib provides Encrypt/Decrypt and Compress/Uncompress functions
|
|
||||||
package rreslib
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/aes"
|
|
||||||
"crypto/cipher"
|
|
||||||
"crypto/des"
|
|
||||||
"crypto/rand"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/blowfish"
|
|
||||||
"golang.org/x/crypto/xtea"
|
|
||||||
|
|
||||||
"github.com/dsnet/compress/bzip2"
|
|
||||||
"github.com/golang/snappy"
|
|
||||||
"github.com/klauspost/compress/flate"
|
|
||||||
"github.com/pierrec/lz4"
|
|
||||||
xor "github.com/rootlch/encrypt"
|
|
||||||
"github.com/ulikunitz/xz"
|
|
||||||
|
|
||||||
"github.com/gen2brain/raylib-go/rres"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Encrypt data
|
|
||||||
func Encrypt(key, data []byte, cryptoType int) ([]byte, error) {
|
|
||||||
switch cryptoType {
|
|
||||||
case rres.CryptoXOR:
|
|
||||||
c, err := xor.NewXor(string(key))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.Encode(data), nil
|
|
||||||
case rres.CryptoAES:
|
|
||||||
b, err := encryptAES(key, data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return b, nil
|
|
||||||
case rres.Crypto3DES:
|
|
||||||
b, err := encrypt3DES(key, data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return b, nil
|
|
||||||
case rres.CryptoBlowfish:
|
|
||||||
b, err := encryptBlowfish(key, data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return b, nil
|
|
||||||
case rres.CryptoXTEA:
|
|
||||||
b, err := encryptXTEA(key, data)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%v\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return b, nil
|
|
||||||
default:
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decrypt data
|
|
||||||
func Decrypt(key, data []byte, cryptoType int) ([]byte, error) {
|
|
||||||
switch cryptoType {
|
|
||||||
case rres.CryptoXOR:
|
|
||||||
c, err := xor.NewXor(string(key))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
b := c.Encode(data)
|
|
||||||
return b, nil
|
|
||||||
case rres.CryptoAES:
|
|
||||||
b, err := decryptAES(key, data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return b, nil
|
|
||||||
case rres.Crypto3DES:
|
|
||||||
b, err := decrypt3DES(key, data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return b, nil
|
|
||||||
case rres.CryptoBlowfish:
|
|
||||||
b, err := decryptBlowfish(key, data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return b, nil
|
|
||||||
case rres.CryptoXTEA:
|
|
||||||
b, err := decryptXTEA(key, data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return b, nil
|
|
||||||
default:
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compress data
|
|
||||||
func Compress(data []byte, compType int) ([]byte, error) {
|
|
||||||
switch compType {
|
|
||||||
case rres.CompNone:
|
|
||||||
return data, nil
|
|
||||||
case rres.CompDeflate:
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
|
|
||||||
w, err := flate.NewWriter(buf, flate.DefaultCompression)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = w.Write(data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Close()
|
|
||||||
|
|
||||||
return buf.Bytes(), nil
|
|
||||||
case rres.CompLZ4:
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
|
|
||||||
w := lz4.NewWriter(buf)
|
|
||||||
|
|
||||||
_, err := w.Write(data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Close()
|
|
||||||
|
|
||||||
return buf.Bytes(), nil
|
|
||||||
case rres.CompLZMA2:
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
|
|
||||||
w, err := xz.NewWriter(buf)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = w.Write(data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Close()
|
|
||||||
|
|
||||||
return buf.Bytes(), nil
|
|
||||||
case rres.CompBZIP2:
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
|
|
||||||
w, err := bzip2.NewWriter(buf, &bzip2.WriterConfig{Level: bzip2.BestCompression})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = w.Write(data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Close()
|
|
||||||
|
|
||||||
return buf.Bytes(), nil
|
|
||||||
case rres.CompSnappy:
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
|
|
||||||
w := snappy.NewWriter(buf)
|
|
||||||
|
|
||||||
_, err := w.Write(data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Close()
|
|
||||||
|
|
||||||
return buf.Bytes(), nil
|
|
||||||
default:
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decompress data
|
|
||||||
func Decompress(data []byte, compType int) ([]byte, error) {
|
|
||||||
switch compType {
|
|
||||||
case rres.CompNone:
|
|
||||||
return data, nil
|
|
||||||
case rres.CompDeflate:
|
|
||||||
r := flate.NewReader(bytes.NewReader(data))
|
|
||||||
|
|
||||||
u, err := ioutil.ReadAll(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
r.Close()
|
|
||||||
|
|
||||||
return u, nil
|
|
||||||
case rres.CompLZ4:
|
|
||||||
r := lz4.NewReader(bytes.NewReader(data))
|
|
||||||
|
|
||||||
u, err := ioutil.ReadAll(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return u, nil
|
|
||||||
case rres.CompLZMA2:
|
|
||||||
r, err := xz.NewReader(bytes.NewReader(data))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
u, err := ioutil.ReadAll(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return u, nil
|
|
||||||
case rres.CompBZIP2:
|
|
||||||
r, err := bzip2.NewReader(bytes.NewReader(data), &bzip2.ReaderConfig{})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
u, err := ioutil.ReadAll(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return u, nil
|
|
||||||
case rres.CompSnappy:
|
|
||||||
r := snappy.NewReader(bytes.NewReader(data))
|
|
||||||
|
|
||||||
u, err := ioutil.ReadAll(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return u, nil
|
|
||||||
default:
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// pad to block size
|
|
||||||
func pad(src []byte, blockSize int) []byte {
|
|
||||||
padding := blockSize - len(src)%blockSize
|
|
||||||
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
|
|
||||||
return append(src, padtext...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// unpad
|
|
||||||
func unpad(src []byte) ([]byte, error) {
|
|
||||||
length := len(src)
|
|
||||||
unpadding := int(src[length-1])
|
|
||||||
|
|
||||||
if unpadding > length {
|
|
||||||
return nil, fmt.Errorf("unpad error. This can happen when incorrect encryption key is used.")
|
|
||||||
}
|
|
||||||
|
|
||||||
return src[:(length - unpadding)], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// encryptAES
|
|
||||||
func encryptAES(key, text []byte) ([]byte, error) {
|
|
||||||
block, err := aes.NewCipher(key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
msg := pad(text, aes.BlockSize)
|
|
||||||
ciphertext := make([]byte, aes.BlockSize+len(msg))
|
|
||||||
iv := ciphertext[:aes.BlockSize]
|
|
||||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
cfb := cipher.NewCFBEncrypter(block, iv)
|
|
||||||
cfb.XORKeyStream(ciphertext[aes.BlockSize:], msg)
|
|
||||||
|
|
||||||
return ciphertext, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// decryptAES
|
|
||||||
func decryptAES(key, text []byte) ([]byte, error) {
|
|
||||||
block, err := aes.NewCipher(key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len(text) % aes.BlockSize) != 0 {
|
|
||||||
return nil, fmt.Errorf("blocksize must be multiple of decoded message length")
|
|
||||||
}
|
|
||||||
|
|
||||||
iv := text[:aes.BlockSize]
|
|
||||||
msg := text[aes.BlockSize:]
|
|
||||||
|
|
||||||
cfb := cipher.NewCFBDecrypter(block, iv)
|
|
||||||
cfb.XORKeyStream(msg, msg)
|
|
||||||
|
|
||||||
unpadMsg, err := unpad(msg)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return unpadMsg, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// encrypt3DES
|
|
||||||
func encrypt3DES(key, text []byte) ([]byte, error) {
|
|
||||||
block, err := des.NewTripleDESCipher(key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
msg := pad(text, des.BlockSize)
|
|
||||||
ciphertext := make([]byte, des.BlockSize+len(msg))
|
|
||||||
iv := ciphertext[:des.BlockSize]
|
|
||||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
cbc := cipher.NewCBCEncrypter(block, iv)
|
|
||||||
cbc.CryptBlocks(ciphertext[des.BlockSize:], msg)
|
|
||||||
|
|
||||||
return ciphertext, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// decrypt3DES
|
|
||||||
func decrypt3DES(key, text []byte) ([]byte, error) {
|
|
||||||
block, err := des.NewCipher(key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len(text) % des.BlockSize) != 0 {
|
|
||||||
return nil, fmt.Errorf("blocksize must be multiple of decoded message length")
|
|
||||||
}
|
|
||||||
|
|
||||||
iv := text[:des.BlockSize]
|
|
||||||
msg := text[des.BlockSize:]
|
|
||||||
|
|
||||||
cbc := cipher.NewCBCDecrypter(block, iv)
|
|
||||||
cbc.CryptBlocks(msg, msg)
|
|
||||||
|
|
||||||
unpadMsg, err := unpad(msg)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return unpadMsg, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// encryptBlowfish
|
|
||||||
func encryptBlowfish(key, text []byte) ([]byte, error) {
|
|
||||||
block, err := blowfish.NewCipher(key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
msg := pad(text, blowfish.BlockSize)
|
|
||||||
ciphertext := make([]byte, blowfish.BlockSize+len(msg))
|
|
||||||
iv := ciphertext[:blowfish.BlockSize]
|
|
||||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
cbc := cipher.NewCBCEncrypter(block, iv)
|
|
||||||
cbc.CryptBlocks(ciphertext[blowfish.BlockSize:], msg)
|
|
||||||
|
|
||||||
return ciphertext, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// decryptBlowfish
|
|
||||||
func decryptBlowfish(key, text []byte) ([]byte, error) {
|
|
||||||
block, err := blowfish.NewCipher(key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len(text) % blowfish.BlockSize) != 0 {
|
|
||||||
return nil, fmt.Errorf("blocksize must be multiple of decoded message length")
|
|
||||||
}
|
|
||||||
|
|
||||||
iv := text[:blowfish.BlockSize]
|
|
||||||
msg := text[blowfish.BlockSize:]
|
|
||||||
|
|
||||||
cbc := cipher.NewCBCDecrypter(block, iv)
|
|
||||||
cbc.CryptBlocks(msg, msg)
|
|
||||||
|
|
||||||
unpadMsg, err := unpad(msg)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return unpadMsg, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// encryptXTEA
|
|
||||||
func encryptXTEA(key, text []byte) ([]byte, error) {
|
|
||||||
block, err := xtea.NewCipher(key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
msg := pad(text, xtea.BlockSize)
|
|
||||||
ciphertext := make([]byte, xtea.BlockSize+len(msg))
|
|
||||||
iv := ciphertext[:xtea.BlockSize]
|
|
||||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
cbc := cipher.NewCBCEncrypter(block, iv)
|
|
||||||
cbc.CryptBlocks(ciphertext[xtea.BlockSize:], msg)
|
|
||||||
|
|
||||||
return ciphertext, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// decryptXTEA
|
|
||||||
func decryptXTEA(key, text []byte) ([]byte, error) {
|
|
||||||
block, err := xtea.NewCipher(key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len(text) % xtea.BlockSize) != 0 {
|
|
||||||
return nil, fmt.Errorf("blocksize must be multiple of decoded message length")
|
|
||||||
}
|
|
||||||
|
|
||||||
iv := text[:xtea.BlockSize]
|
|
||||||
msg := text[xtea.BlockSize:]
|
|
||||||
|
|
||||||
cbc := cipher.NewCBCDecrypter(block, iv)
|
|
||||||
cbc.CryptBlocks(msg, msg)
|
|
||||||
|
|
||||||
unpadMsg, err := unpad(msg)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return unpadMsg, nil
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue