first commit

This commit is contained in:
lnk
2026-07-10 14:13:02 +08:00
commit b61388443f
459 changed files with 143602 additions and 0 deletions

View File

@@ -0,0 +1,16 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
add_subdirectory(signature)

View File

@@ -0,0 +1,29 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
project(signature)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
set(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/lib)
aux_source_directory(src/ DIR_LIB_SRCS)
add_library(Signature STATIC ${DIR_LIB_SRCS})
target_link_libraries(Signature ${deplibs})
set_target_properties(Signature PROPERTIES OUTPUT_NAME "Signature")
# install
install(TARGETS Signature DESTINATION lib)
#install (DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/ DESTINATION include/rocketmq)

View File

@@ -0,0 +1,49 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef BASE64_H
#define BASE64_H
/* Get size_t. */
#include <stddef.h>
/* Get bool. */
#include <stdbool.h>
#ifdef __cplusplus
namespace rocketmqSignature {
#endif
/* This uses that the expression (n+(k-1))/k means the smallest
integer >= n/k, i.e., the ceiling of n/k. */
#define BASE64_LENGTH(inlen) ((((inlen) + 2) / 3) * 4)
extern bool isbase64(char ch);
extern void base64_encode(const char* in, size_t inlen, char* out, size_t outlen);
extern size_t base64_encode_alloc(const char* in, size_t inlen, char** out);
extern bool base64_decode(const char* in, size_t inlen, char* out, size_t* outlen);
extern bool base64_decode_alloc(const char* in, size_t inlen, char** out, size_t* outlen);
#ifdef __cplusplus
}
#endif
#endif /* BASE64_H */

View File

@@ -0,0 +1,70 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _HMAC_HMAC_H
#define _HMAC_HMAC_H
#ifdef __cplusplus
extern "C" {
#endif
#include <sys/types.h>
#ifndef SHA1_DIGEST_LEN
#define SHA1_DIGEST_LEN 20
#endif
#ifndef SHA256_DIGEST_LEN
#define SHA256_DIGEST_LEN 32
#endif
#ifndef SHA512_DIGEST_LEN
#define SHA512_DIGEST_LEN 64
#endif
/*
* hmac_sha1:
* hmac_sha256:
* hmac_sha512:
* Calculate Hashed Message Authentication Code with sha1/256/512 algorithm
* Caution: ret_buf should provide enough space for HMAC result.
*
* @key [in]: the secure-key string
* @key_len [in]: the length of secure-key
* @data [in]: data string could be calculated.
* @data_len [in]: the length of data. length is needed because strlen could not take effect.
* @ret_buf [out]: HMAC result stored in ret_buf.
*/
#ifdef __cplusplus
namespace rocketmqSignature {
#endif
extern int hmac_sha1(const void* key, size_t key_len, const void* data, size_t data_len, void* ret_buf);
extern int hmac_sha256(const void* key, size_t key_len, const void* data, size_t data_len, void* ret_buf);
extern int hmac_sha512(const void* key, size_t key_len, const void* data, size_t data_len, void* ret_buf);
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,54 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PARAM_LIST_H
#define PARAM_LIST_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
namespace rocketmqSignature {
#endif
typedef struct _spas_param_node {
char* name;
char* value;
struct _spas_param_node* pnext;
} SPAS_PARAM_NODE;
typedef struct _spas_param_list {
SPAS_PARAM_NODE* phead;
unsigned int length; /* count of nodes */
unsigned int size; /* total size of string presentation */
} SPAS_PARAM_LIST;
extern SPAS_PARAM_LIST* create_param_list(void);
extern int add_param_to_list(SPAS_PARAM_LIST* list, const char* name, const char* value);
extern void free_param_list(SPAS_PARAM_LIST* list);
extern char* param_list_to_str(const SPAS_PARAM_LIST* list);
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,84 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SHA1_H
#define SHA1_H 1
#include <stdio.h>
#include <stdint.h>
#ifdef __cplusplus
namespace rocketmqSignature {
#endif
#define SHA1_DIGEST_SIZE 20
/* Structure to save state of computation between the single steps. */
struct sha1_ctx {
uint32_t A;
uint32_t B;
uint32_t C;
uint32_t D;
uint32_t E;
uint32_t total[2];
uint32_t buflen;
uint32_t buffer[32];
};
/* Initialize structure containing state of computation. */
extern void sha1_init_ctx(struct sha1_ctx* ctx);
/* Starting with the result of former calls of this function (or the
initialization function update the context for the next LEN bytes
starting at BUFFER.
It is necessary that LEN is a multiple of 64!!! */
extern void sha1_process_block(const void* buffer, size_t len, struct sha1_ctx* ctx);
/* Starting with the result of former calls of this function (or the
initialization function update the context for the next LEN bytes
starting at BUFFER.
It is NOT required that LEN is a multiple of 64. */
extern void sha1_process_bytes(const void* buffer, size_t len, struct sha1_ctx* ctx);
/* Process the remaining bytes in the buffer and put result from CTX
in first 20 bytes following RESBUF. The result is always in little
endian byte order, so that a byte-wise output yields to the wanted
ASCII representation of the message digest. */
extern void* sha1_finish_ctx(struct sha1_ctx* ctx, void* resbuf);
/* Put result from CTX in first 20 bytes following RESBUF. The result is
always in little endian byte order, so that a byte-wise output yields
to the wanted ASCII representation of the message digest. */
extern void* sha1_read_ctx(const struct sha1_ctx* ctx, void* resbuf);
/* Compute SHA1 message digest for bytes read from STREAM. The
resulting message digest number will be written into the 20 bytes
beginning at RESBLOCK. */
extern int sha1_stream(FILE* stream, void* resblock);
/* Compute SHA1 message digest for LEN bytes beginning at BUFFER. The
result is always in little endian byte order, so that a byte-wise
output yields to the wanted ASCII representation of the message
digest. */
extern void* sha1_buffer(const char* buffer, size_t len, void* resblock);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,86 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SHA256_H
#define SHA256_H 1
#include <stdio.h>
#include <stdint.h>
#ifdef __cplusplus
namespace rocketmqSignature {
#endif
/* Structure to save state of computation between the single steps. */
struct sha256_ctx {
uint32_t state[8];
uint32_t total[2];
size_t buflen;
uint32_t buffer[32];
};
enum { SHA224_DIGEST_SIZE = 28 };
enum { SHA256_DIGEST_SIZE = 32 };
/* Initialize structure containing state of computation. */
extern void sha256_init_ctx(struct sha256_ctx* ctx);
extern void sha224_init_ctx(struct sha256_ctx* ctx);
/* Starting with the result of former calls of this function (or the
initialization function update the context for the next LEN bytes
starting at BUFFER.
It is necessary that LEN is a multiple of 64!!! */
extern void sha256_process_block(const void* buffer, size_t len, struct sha256_ctx* ctx);
/* Starting with the result of former calls of this function (or the
initialization function update the context for the next LEN bytes
starting at BUFFER.
It is NOT required that LEN is a multiple of 64. */
extern void sha256_process_bytes(const void* buffer, size_t len, struct sha256_ctx* ctx);
/* Process the remaining bytes in the buffer and put result from CTX
in first 32 (28) bytes following RESBUF. The result is always in little
endian byte order, so that a byte-wise output yields to the wanted
ASCII representation of the message digest. */
extern void* sha256_finish_ctx(struct sha256_ctx* ctx, void* resbuf);
extern void* sha224_finish_ctx(struct sha256_ctx* ctx, void* resbuf);
/* Put result from CTX in first 32 (28) bytes following RESBUF. The result is
always in little endian byte order, so that a byte-wise output yields
to the wanted ASCII representation of the message digest. */
extern void* sha256_read_ctx(const struct sha256_ctx* ctx, void* resbuf);
extern void* sha224_read_ctx(const struct sha256_ctx* ctx, void* resbuf);
/* Compute SHA256 (SHA224) message digest for bytes read from STREAM. The
resulting message digest number will be written into the 32 (28) bytes
beginning at RESBLOCK. */
extern int sha256_stream(FILE* stream, void* resblock);
extern int sha224_stream(FILE* stream, void* resblock);
/* Compute SHA256 (SHA224) message digest for LEN bytes beginning at BUFFER. The
result is always in little endian byte order, so that a byte-wise
output yields to the wanted ASCII representation of the message
digest. */
extern void* sha256_buffer(const char* buffer, size_t len, void* resblock);
extern void* sha224_buffer(const char* buffer, size_t len, void* resblock);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,90 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SHA512_H
#define SHA512_H 1
#include <stdio.h>
#include "u64.h"
#ifdef __cplusplus
namespace rocketmqSignature {
#endif
/* Structure to save state of computation between the single steps. */
struct sha512_ctx {
u64 state[8];
u64 total[2];
size_t buflen;
u64 buffer[32];
};
enum { SHA384_DIGEST_SIZE = 48 };
enum { SHA512_DIGEST_SIZE = 64 };
/* Initialize structure containing state of computation. */
extern void sha512_init_ctx(struct sha512_ctx* ctx);
extern void sha384_init_ctx(struct sha512_ctx* ctx);
/* Starting with the result of former calls of this function (or the
initialization function update the context for the next LEN bytes
starting at BUFFER.
It is necessary that LEN is a multiple of 128!!! */
extern void sha512_process_block(const void* buffer, size_t len, struct sha512_ctx* ctx);
/* Starting with the result of former calls of this function (or the
initialization function update the context for the next LEN bytes
starting at BUFFER.
It is NOT required that LEN is a multiple of 128. */
extern void sha512_process_bytes(const void* buffer, size_t len, struct sha512_ctx* ctx);
/* Process the remaining bytes in the buffer and put result from CTX
in first 64 (48) bytes following RESBUF. The result is always in little
endian byte order, so that a byte-wise output yields to the wanted
ASCII representation of the message digest. */
extern void* sha512_finish_ctx(struct sha512_ctx* ctx, void* resbuf);
extern void* sha384_finish_ctx(struct sha512_ctx* ctx, void* resbuf);
/* Put result from CTX in first 64 (48) bytes following RESBUF. The result is
always in little endian byte order, so that a byte-wise output yields
to the wanted ASCII representation of the message digest.
IMPORTANT: On some systems it is required that RESBUF is correctly
aligned for a 32 bits value. */
extern void* sha512_read_ctx(const struct sha512_ctx* ctx, void* resbuf);
extern void* sha384_read_ctx(const struct sha512_ctx* ctx, void* resbuf);
/* Compute SHA512 (SHA384) message digest for bytes read from STREAM. The
resulting message digest number will be written into the 64 (48) bytes
beginning at RESBLOCK. */
extern int sha512_stream(FILE* stream, void* resblock);
extern int sha384_stream(FILE* stream, void* resblock);
/* Compute SHA512 (SHA384) message digest for LEN bytes beginning at BUFFER. The
result is always in little endian byte order, so that a byte-wise
output yields to the wanted ASCII representation of the message
digest. */
extern void* sha512_buffer(const char* buffer, size_t len, void* resblock);
extern void* sha384_buffer(const char* buffer, size_t len, void* resblock);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,103 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SPAS_CLIENT_H
#define SPAS_CLIENT_H
#include "param_list.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
namespace rocketmqSignature {
#endif
#define SPAS_MAX_KEY_LEN 128 /* max access_key/secret_key length */
#define SPAS_MAX_PATH 256 /* max credential file path length */
#define SPAS_ACCESS_KEY_TAG \
"accessKey" /* access_key tag in credential file \
*/
#define SPAS_SECRET_KEY_TAG \
"secretKey" /* secret_key tag in credential file \
*/
#define SPAS_CREDENTIAL_ENV "SPAS_CREDENTIAL" /* credential file environment variable */
typedef enum {
SIGN_HMACSHA1 = 0, /* HmacSHA1 */
SIGN_HMACSHA256 = 1, /* HmacSHA256 */
} SPAS_SIGN_ALGORITHM;
typedef enum {
NO_UPDATE = 0, /* do not update credential */
UPDATE_BY_ALARM = 1, /* update credential by SIGALRM */
#ifdef SPAS_MT
UPDATE_BY_THREAD = 2, /* update credential by standalone thread */
#endif
} CREDENTIAL_UPDATE_MODE;
typedef enum {
SPAS_NO_ERROR = 0, /* success */
ERROR_INVALID_PARAM = -1, /* invalid parameter */
ERROR_NO_CREDENTIAL = -2, /* credential file not specified */
ERROR_FILE_OPEN = -3, /* file open failed */
ERROR_MEM_ALLOC = -4, /* memory allocation failed */
ERROR_MISSING_KEY = -5, /* missing access_key/secret_key */
ERROR_KEY_LENGTH = -6, /* key length exceed limit */
ERROR_UPDATE_CREDENTIAL = -7 /* update credential file failed */
} SPAS_ERROR_CODE;
typedef struct _spas_credential {
char access_key[SPAS_MAX_KEY_LEN];
char secret_key[SPAS_MAX_KEY_LEN];
} SPAS_CREDENTIAL;
extern int spas_load_credential(char* path, CREDENTIAL_UPDATE_MODE mode);
extern int spas_set_access_key(char* key);
extern int spas_set_secret_key(char* key);
extern char* spas_get_access_key(void);
extern char* spas_get_secret_key(void);
extern SPAS_CREDENTIAL* spas_get_credential(void);
#ifdef SPAS_MT
extern int spas_load_thread_credential(char* path);
extern int spas_set_thread_access_key(char* key);
extern int spas_set_thread_secret_key(char* key);
extern char* spas_get_thread_access_key(void);
extern char* spas_get_thread_secret_key(void);
#endif
extern char* spas_get_signature(const SPAS_PARAM_LIST* list, const char* key);
extern char* spas_get_signature2(const SPAS_PARAM_LIST* list, const char* key, SPAS_SIGN_ALGORITHM algorithm);
extern char* spas_sign(const char* data, size_t size, const char* key);
extern char* spas_sign2(const char* data, size_t size, const char* key, SPAS_SIGN_ALGORITHM algorithm);
extern void spas_mem_free(char* pSignature);
extern char* spas_get_version(void);
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,135 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stddef.h>
#include <stdint.h>
/* Return X rotated left by N bits, where 0 < N < 64. */
#define u64rol(x, n) u64or(u64shl(x, n), u64shr(x, 64 - n))
#ifdef UINT64_MAX
/* Native implementations are trivial. See below for comments on what
these operations do. */
typedef uint64_t u64;
#define u64hilo(hi, lo) ((u64)(((u64)(hi) << 32) + (lo)))
#define u64init(hi, lo) u64hilo(hi, lo)
#define u64lo(x) ((u64)(x))
#define u64lt(x, y) ((x) < (y))
#define u64and(x, y) ((x) & (y))
#define u64or(x, y) ((x) | (y))
#define u64xor(x, y) ((x) ^ (y))
#define u64plus(x, y) ((x) + (y))
#define u64shl(x, n) ((x) << (n))
#define u64shr(x, n) ((x) >> (n))
#else
/* u64 is a 64-bit unsigned integer value.
u64init (HI, LO), is like u64hilo (HI, LO), but for use in
initializer contexts. */
#ifdef WORDS_BIGENDIAN
typedef struct { uint32_t hi, lo; } u64;
#define u64init(hi, lo) \
{ hi, lo }
#else
typedef struct { uint32_t lo, hi; } u64;
#define u64init(hi, lo) \
{ lo, hi }
#endif
/* Given the high and low-order 32-bit quantities HI and LO, return a u64
value representing (HI << 32) + LO. */
static inline u64 u64hilo(uint32_t hi, uint32_t lo) {
u64 r;
r.hi = hi;
r.lo = lo;
return r;
}
/* Return a u64 value representing LO. */
static inline u64 u64lo(uint32_t lo) {
u64 r;
r.hi = 0;
r.lo = lo;
return r;
}
/* Return X < Y. */
static inline int u64lt(u64 x, u64 y) {
return x.hi < y.hi || (x.hi == y.hi && x.lo < y.lo);
}
/* Return X & Y. */
static inline u64 u64and(u64 x, u64 y) {
u64 r;
r.hi = x.hi & y.hi;
r.lo = x.lo & y.lo;
return r;
}
/* Return X | Y. */
static inline u64 u64or(u64 x, u64 y) {
u64 r;
r.hi = x.hi | y.hi;
r.lo = x.lo | y.lo;
return r;
}
/* Return X ^ Y. */
static inline u64 u64xor(u64 x, u64 y) {
u64 r;
r.hi = x.hi ^ y.hi;
r.lo = x.lo ^ y.lo;
return r;
}
/* Return X + Y. */
static inline u64 u64plus(u64 x, u64 y) {
u64 r;
r.lo = x.lo + y.lo;
r.hi = x.hi + y.hi + (r.lo < x.lo);
return r;
}
/* Return X << N. */
static inline u64 u64shl(u64 x, int n) {
u64 r;
if (n < 32) {
r.hi = (x.hi << n) | (x.lo >> (32 - n));
r.lo = x.lo << n;
} else {
r.hi = x.lo << (n - 32);
r.lo = 0;
}
return r;
}
/* Return X >> N. */
static inline u64 u64shr(u64 x, int n) {
u64 r;
if (n < 32) {
r.hi = x.hi >> n;
r.lo = (x.hi << (32 - n)) | (x.lo >> n);
} else {
r.hi = 0;
r.lo = x.hi >> (n - 32);
}
return r;
}
#endif

View File

@@ -0,0 +1,409 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Get prototype. */
#include "base64.h"
/* Get malloc. */
#include <stdlib.h>
/* Get UCHAR_MAX. */
#include <limits.h>
#ifdef __cplusplus
namespace rocketmqSignature{
#endif
/* C89 compliant way to cast 'char' to 'unsigned char'. */
#ifdef WIN32
static _inline unsigned char
#else
static inline unsigned char
#endif
to_uchar (char ch)
{
return ch;
}
/* Base64 encode IN array of size INLEN into OUT array of size OUTLEN.
If OUTLEN is less than BASE64_LENGTH(INLEN), write as many bytes as
possible. If OUTLEN is larger than BASE64_LENGTH(INLEN), also zero
terminate the output buffer. */
void
base64_encode (const char *in, size_t inlen,
char *out, size_t outlen)
{
static const char b64str[65] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
while (inlen && outlen)
{
*out++ = b64str[(to_uchar (in[0]) >> 2) & 0x3f];
if (!--outlen)
break;
*out++ = b64str[((to_uchar (in[0]) << 4)
+ (--inlen ? to_uchar (in[1]) >> 4 : 0))
& 0x3f];
if (!--outlen)
break;
*out++ =
(inlen
? b64str[((to_uchar (in[1]) << 2)
+ (--inlen ? to_uchar (in[2]) >> 6 : 0))
& 0x3f]
: '=');
if (!--outlen)
break;
*out++ = inlen ? b64str[to_uchar (in[2]) & 0x3f] : '=';
if (!--outlen)
break;
if (inlen)
inlen--;
if (inlen)
in += 3;
}
if (outlen)
*out = '\0';
}
/* Allocate a buffer and store zero terminated base64 encoded data
from array IN of size INLEN, returning BASE64_LENGTH(INLEN), i.e.,
the length of the encoded data, excluding the terminating zero. On
return, the OUT variable will hold a pointer to newly allocated
memory that must be deallocated by the caller. If output string
length would overflow, 0 is returned and OUT is set to NULL. If
memory allocation failed, OUT is set to NULL, and the return value
indicates length of the requested memory block, i.e.,
BASE64_LENGTH(inlen) + 1. */
size_t
base64_encode_alloc (const char *in, size_t inlen, char **out)
{
size_t outlen = 1 + BASE64_LENGTH (inlen);
/* Check for overflow in outlen computation.
*
* If there is no overflow, outlen >= inlen.
*
* If the operation (inlen + 2) overflows then it yields at most +1, so
* outlen is 0.
*
* If the multiplication overflows, we lose at least half of the
* correct value, so the result is < ((inlen + 2) / 3) * 2, which is
* less than (inlen + 2) * 0.66667, which is less than inlen as soon as
* (inlen > 4).
*/
if (inlen > outlen)
{
*out = NULL;
return 0;
}
*out = (char *)malloc (outlen);
if (!*out)
return outlen;
base64_encode (in, inlen, *out, outlen);
return outlen - 1;
}
/* With this approach this file works independent of the charset used
(think EBCDIC). However, it does assume that the characters in the
Base64 alphabet (A-Za-z0-9+/) are encoded in 0..255. POSIX
1003.1-2001 require that char and unsigned char are 8-bit
quantities, though, taking care of that problem. But this may be a
potential problem on non-POSIX C99 platforms.
IBM C V6 for AIX mishandles "#define B64(x) ...'x'...", so use "_"
as the formal parameter rather than "x". */
#define B64(_) \
((_) == 'A' ? 0 \
: (_) == 'B' ? 1 \
: (_) == 'C' ? 2 \
: (_) == 'D' ? 3 \
: (_) == 'E' ? 4 \
: (_) == 'F' ? 5 \
: (_) == 'G' ? 6 \
: (_) == 'H' ? 7 \
: (_) == 'I' ? 8 \
: (_) == 'J' ? 9 \
: (_) == 'K' ? 10 \
: (_) == 'L' ? 11 \
: (_) == 'M' ? 12 \
: (_) == 'N' ? 13 \
: (_) == 'O' ? 14 \
: (_) == 'P' ? 15 \
: (_) == 'Q' ? 16 \
: (_) == 'R' ? 17 \
: (_) == 'S' ? 18 \
: (_) == 'T' ? 19 \
: (_) == 'U' ? 20 \
: (_) == 'V' ? 21 \
: (_) == 'W' ? 22 \
: (_) == 'X' ? 23 \
: (_) == 'Y' ? 24 \
: (_) == 'Z' ? 25 \
: (_) == 'a' ? 26 \
: (_) == 'b' ? 27 \
: (_) == 'c' ? 28 \
: (_) == 'd' ? 29 \
: (_) == 'e' ? 30 \
: (_) == 'f' ? 31 \
: (_) == 'g' ? 32 \
: (_) == 'h' ? 33 \
: (_) == 'i' ? 34 \
: (_) == 'j' ? 35 \
: (_) == 'k' ? 36 \
: (_) == 'l' ? 37 \
: (_) == 'm' ? 38 \
: (_) == 'n' ? 39 \
: (_) == 'o' ? 40 \
: (_) == 'p' ? 41 \
: (_) == 'q' ? 42 \
: (_) == 'r' ? 43 \
: (_) == 's' ? 44 \
: (_) == 't' ? 45 \
: (_) == 'u' ? 46 \
: (_) == 'v' ? 47 \
: (_) == 'w' ? 48 \
: (_) == 'x' ? 49 \
: (_) == 'y' ? 50 \
: (_) == 'z' ? 51 \
: (_) == '0' ? 52 \
: (_) == '1' ? 53 \
: (_) == '2' ? 54 \
: (_) == '3' ? 55 \
: (_) == '4' ? 56 \
: (_) == '5' ? 57 \
: (_) == '6' ? 58 \
: (_) == '7' ? 59 \
: (_) == '8' ? 60 \
: (_) == '9' ? 61 \
: (_) == '+' ? 62 \
: (_) == '/' ? 63 \
: -1)
static const signed char b64[0x100] = {
B64 (0), B64 (1), B64 (2), B64 (3),
B64 (4), B64 (5), B64 (6), B64 (7),
B64 (8), B64 (9), B64 (10), B64 (11),
B64 (12), B64 (13), B64 (14), B64 (15),
B64 (16), B64 (17), B64 (18), B64 (19),
B64 (20), B64 (21), B64 (22), B64 (23),
B64 (24), B64 (25), B64 (26), B64 (27),
B64 (28), B64 (29), B64 (30), B64 (31),
B64 (32), B64 (33), B64 (34), B64 (35),
B64 (36), B64 (37), B64 (38), B64 (39),
B64 (40), B64 (41), B64 (42), B64 (43),
B64 (44), B64 (45), B64 (46), B64 (47),
B64 (48), B64 (49), B64 (50), B64 (51),
B64 (52), B64 (53), B64 (54), B64 (55),
B64 (56), B64 (57), B64 (58), B64 (59),
B64 (60), B64 (61), B64 (62), B64 (63),
B64 (64), B64 (65), B64 (66), B64 (67),
B64 (68), B64 (69), B64 (70), B64 (71),
B64 (72), B64 (73), B64 (74), B64 (75),
B64 (76), B64 (77), B64 (78), B64 (79),
B64 (80), B64 (81), B64 (82), B64 (83),
B64 (84), B64 (85), B64 (86), B64 (87),
B64 (88), B64 (89), B64 (90), B64 (91),
B64 (92), B64 (93), B64 (94), B64 (95),
B64 (96), B64 (97), B64 (98), B64 (99),
B64 (100), B64 (101), B64 (102), B64 (103),
B64 (104), B64 (105), B64 (106), B64 (107),
B64 (108), B64 (109), B64 (110), B64 (111),
B64 (112), B64 (113), B64 (114), B64 (115),
B64 (116), B64 (117), B64 (118), B64 (119),
B64 (120), B64 (121), B64 (122), B64 (123),
B64 (124), B64 (125), B64 (126), B64 (127),
B64 (128), B64 (129), B64 (130), B64 (131),
B64 (132), B64 (133), B64 (134), B64 (135),
B64 (136), B64 (137), B64 (138), B64 (139),
B64 (140), B64 (141), B64 (142), B64 (143),
B64 (144), B64 (145), B64 (146), B64 (147),
B64 (148), B64 (149), B64 (150), B64 (151),
B64 (152), B64 (153), B64 (154), B64 (155),
B64 (156), B64 (157), B64 (158), B64 (159),
B64 (160), B64 (161), B64 (162), B64 (163),
B64 (164), B64 (165), B64 (166), B64 (167),
B64 (168), B64 (169), B64 (170), B64 (171),
B64 (172), B64 (173), B64 (174), B64 (175),
B64 (176), B64 (177), B64 (178), B64 (179),
B64 (180), B64 (181), B64 (182), B64 (183),
B64 (184), B64 (185), B64 (186), B64 (187),
B64 (188), B64 (189), B64 (190), B64 (191),
B64 (192), B64 (193), B64 (194), B64 (195),
B64 (196), B64 (197), B64 (198), B64 (199),
B64 (200), B64 (201), B64 (202), B64 (203),
B64 (204), B64 (205), B64 (206), B64 (207),
B64 (208), B64 (209), B64 (210), B64 (211),
B64 (212), B64 (213), B64 (214), B64 (215),
B64 (216), B64 (217), B64 (218), B64 (219),
B64 (220), B64 (221), B64 (222), B64 (223),
B64 (224), B64 (225), B64 (226), B64 (227),
B64 (228), B64 (229), B64 (230), B64 (231),
B64 (232), B64 (233), B64 (234), B64 (235),
B64 (236), B64 (237), B64 (238), B64 (239),
B64 (240), B64 (241), B64 (242), B64 (243),
B64 (244), B64 (245), B64 (246), B64 (247),
B64 (248), B64 (249), B64 (250), B64 (251),
B64 (252), B64 (253), B64 (254), B64 (255)
};
#if UCHAR_MAX == 255
# define uchar_in_range(c) true
#else
# define uchar_in_range(c) ((c) <= 255)
#endif
/* Return true if CH is a character from the Base64 alphabet, and
false otherwise. Note that '=' is padding and not considered to be
part of the alphabet. */
bool
isbase64 (char ch)
{
return uchar_in_range (to_uchar (ch)) && 0 <= b64[to_uchar (ch)];
}
/* Decode base64 encoded input array IN of length INLEN to output
array OUT that can hold *OUTLEN bytes. Return true if decoding was
successful, i.e. if the input was valid base64 data, false
otherwise. If *OUTLEN is too small, as many bytes as possible will
be written to OUT. On return, *OUTLEN holds the length of decoded
bytes in OUT. Note that as soon as any non-alphabet characters are
encountered, decoding is stopped and false is returned. This means
that, when applicable, you must remove any line terminators that is
part of the data stream before calling this function. */
bool
base64_decode (const char *in, size_t inlen,
char *out, size_t *outlen)
{
size_t outleft = *outlen;
while (inlen >= 2)
{
if (!isbase64 (in[0]) || !isbase64 (in[1]))
break;
if (outleft)
{
*out++ = ((b64[to_uchar (in[0])] << 2)
| (b64[to_uchar (in[1])] >> 4));
outleft--;
}
if (inlen == 2)
break;
if (in[2] == '=')
{
if (inlen != 4)
break;
if (in[3] != '=')
break;
}
else
{
if (!isbase64 (in[2]))
break;
if (outleft)
{
*out++ = (((b64[to_uchar (in[1])] << 4) & 0xf0)
| (b64[to_uchar (in[2])] >> 2));
outleft--;
}
if (inlen == 3)
break;
if (in[3] == '=')
{
if (inlen != 4)
break;
}
else
{
if (!isbase64 (in[3]))
break;
if (outleft)
{
*out++ = (((b64[to_uchar (in[2])] << 6) & 0xc0)
| b64[to_uchar (in[3])]);
outleft--;
}
}
}
in += 4;
inlen -= 4;
}
*outlen -= outleft;
if (inlen != 0)
return false;
return true;
}
/* Allocate an output buffer in *OUT, and decode the base64 encoded
data stored in IN of size INLEN to the *OUT buffer. On return, the
size of the decoded data is stored in *OUTLEN. OUTLEN may be NULL,
if the caller is not interested in the decoded length. *OUT may be
NULL to indicate an out of memory error, in which case *OUTLEN
contains the size of the memory block needed. The function returns
true on successful decoding and memory allocation errors. (Use the
*OUT and *OUTLEN parameters to differentiate between successful
decoding and memory error.) The function returns false if the
input was invalid, in which case *OUT is NULL and *OUTLEN is
undefined. */
bool
base64_decode_alloc (const char *in, size_t inlen, char **out,
size_t *outlen)
{
/* This may allocate a few bytes too much, depending on input,
but it's not worth the extra CPU time to compute the exact amount.
The exact amount is 3 * inlen / 4, minus 1 if the input ends
with "=" and minus another 1 if the input ends with "==".
Dividing before multiplying avoids the possibility of overflow. */
size_t needlen = 3 * (inlen / 4) + 2;
*out = (char *)malloc (needlen);
if (!*out)
return true;
if (!base64_decode (in, inlen, *out, &needlen))
{
free (*out);
*out = NULL;
return false;
}
if (outlen)
*outlen = needlen;
return true;
#ifdef __cplusplus
}
#endif
}

View File

@@ -0,0 +1,181 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <string.h>
#include <stdint.h>
#include "hmac.h"
#include "sha1.h"
#include "sha256.h"
#include "sha512.h"
#ifdef __cplusplus
namespace rocketmqSignature{
#endif
#define IPAD 0x36
#define OPAD 0x5c
int hmac_sha1(const void *key, size_t key_len, const void *data, size_t data_len, void *ret_buf)
{
uint32_t i;
struct sha1_ctx inner;
struct sha1_ctx outer;
struct sha1_ctx key_hash;
char ipad[64] = {0};
char opad[64] = {0};
char key_buf[SHA1_DIGEST_SIZE] = {0};
char inner_buf[SHA1_DIGEST_SIZE] = {0};
if (key == NULL || data == NULL || ret_buf == NULL) return -1;
if (key_len > 64) {
sha1_init_ctx(&key_hash);
sha1_process_bytes(key, key_len, &key_hash);
sha1_finish_ctx(&key_hash, key_buf);
key = key_buf;
key_len = SHA1_DIGEST_SIZE;
}
sha1_init_ctx (&inner);
for (i = 0; i < 64; i++) {
if (i < key_len) {
ipad[i] = ((const char *)key)[i] ^ IPAD;
opad[i] = ((const char *)key)[i] ^ OPAD;
} else {
ipad[i] = IPAD;
opad[i] = OPAD;
}
}
sha1_process_block (ipad, 64, &inner);
sha1_process_bytes (data, data_len, &inner);
sha1_finish_ctx (&inner, inner_buf);
sha1_init_ctx (&outer);
sha1_process_block (opad, 64, &outer);
sha1_process_bytes (inner_buf, SHA1_DIGEST_SIZE, &outer);
sha1_finish_ctx (&outer, ret_buf);
return 0;
}
int hmac_sha256(const void *key, size_t key_len, const void *data, size_t data_len, void *ret_buf)
{
uint32_t i;
struct sha256_ctx inner;
struct sha256_ctx outer;
struct sha256_ctx key_hash;
char ipad[64] = {0};
char opad[64] = {0};
char key_buf[SHA256_DIGEST_SIZE] = {0};
char inner_buf[SHA256_DIGEST_SIZE] = {0};
if (key == NULL || data == NULL || ret_buf == NULL) return -1;
if (key_len > 64) {
sha256_init_ctx(&key_hash);
sha256_process_bytes(key, key_len, &key_hash);
sha256_finish_ctx(&key_hash, key_buf);
key = key_buf;
key_len = SHA256_DIGEST_SIZE;
}
sha256_init_ctx (&inner);
for (i = 0; i < 64; i++) {
if (i < key_len) {
ipad[i] = ((const char *)key)[i] ^ IPAD;
opad[i] = ((const char *)key)[i] ^ OPAD;
} else {
ipad[i] = IPAD;
opad[i] = OPAD;
}
}
sha256_process_block (ipad, 64, &inner);
sha256_process_bytes (data, data_len, &inner);
sha256_finish_ctx (&inner, inner_buf);
sha256_init_ctx (&outer);
sha256_process_block (opad, 64, &outer);
sha256_process_bytes (inner_buf, SHA256_DIGEST_SIZE, &outer);
sha256_finish_ctx (&outer, ret_buf);
return 0;
}
int hmac_sha512(const void *key, size_t key_len, const void *data, size_t data_len, void *ret_buf)
{
uint32_t i;
struct sha512_ctx inner;
struct sha512_ctx outer;
struct sha512_ctx key_hash;
char ipad[128] = {0};
char opad[128] = {0};
char key_buf[SHA512_DIGEST_SIZE] = {0};
char inner_buf[SHA512_DIGEST_SIZE] = {0};
if (key == NULL || data == NULL || ret_buf == NULL) return -1;
if (key_len > 128) {
sha512_init_ctx(&key_hash);
sha512_process_bytes(key, key_len, &key_hash);
sha512_finish_ctx(&key_hash, key_buf);
key = key_buf;
key_len = SHA512_DIGEST_SIZE;
}
sha512_init_ctx (&inner);
for (i = 0; i < 128; i++) {
if (i < key_len) {
ipad[i] = ((const char *)key)[i] ^ IPAD;
opad[i] = ((const char *)key)[i] ^ OPAD;
} else {
ipad[i] = IPAD;
opad[i] = OPAD;
}
}
sha512_process_block (ipad, 128, &inner);
sha512_process_bytes (data, data_len, &inner);
sha512_finish_ctx (&inner, inner_buf);
sha512_init_ctx (&outer);
sha512_process_block (opad, 128, &outer);
sha512_process_bytes (inner_buf, SHA512_DIGEST_SIZE, &outer);
sha512_finish_ctx (&outer, ret_buf);
return 0;
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,142 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <string.h>
#include "spas_client.h"
#ifdef __cplusplus
namespace rocketmqSignature {
#endif
extern void *_mem_alloc(unsigned int size);
extern void _mem_free(void *ptr);
static int _nodecmp(SPAS_PARAM_NODE *n1, SPAS_PARAM_NODE *n2) {
int ret = strcmp(n1->name, n2->name);
if (ret == 0) {
ret = strcmp(n1->value, n2->value);
}
return ret;
}
SPAS_PARAM_LIST *create_param_list() {
return (SPAS_PARAM_LIST *)_mem_alloc(sizeof(SPAS_PARAM_LIST));
}
void free_param_list(SPAS_PARAM_LIST *list) {
SPAS_PARAM_NODE *pnode = NULL;
SPAS_PARAM_NODE *pnext = NULL;
if (list == NULL) {
return;
}
pnode = list->phead;
while (pnode != NULL) {
pnext = pnode->pnext;
_mem_free(pnode->name);
_mem_free(pnode->value);
_mem_free(pnode);
pnode = pnext;
}
_mem_free(list);
}
int add_param_to_list(SPAS_PARAM_LIST *list, const char *name,
const char *value) {
SPAS_PARAM_NODE *pnode = NULL;
SPAS_PARAM_NODE *plast = NULL;
int nlen = 0;
int vlen = 0;
if (list == NULL || name == NULL || value == NULL) {
return ERROR_INVALID_PARAM;
}
nlen = strlen(name);
vlen = strlen(value);
pnode = (SPAS_PARAM_NODE *)_mem_alloc(sizeof(SPAS_PARAM_NODE));
if (pnode == NULL) {
return ERROR_MEM_ALLOC;
}
pnode->name = (char *)_mem_alloc(nlen + 1);
if (pnode->name == NULL) {
_mem_free(pnode);
return ERROR_MEM_ALLOC;
}
pnode->value = (char *)_mem_alloc(vlen + 1);
if (pnode->value == NULL) {
_mem_free(pnode->name);
_mem_free(pnode);
return ERROR_MEM_ALLOC;
}
memcpy(pnode->name, name, nlen);
memcpy(pnode->value, value, vlen);
if (list->phead == NULL) {
list->phead = pnode;
} else if (_nodecmp(pnode, list->phead) <= 0) {
pnode->pnext = list->phead;
list->phead = pnode;
} else {
plast = list->phead;
while (plast->pnext != NULL) {
if (_nodecmp(pnode, plast->pnext) <= 0) {
pnode->pnext = plast->pnext;
plast->pnext = pnode;
break;
} else {
plast = plast->pnext;
}
}
if (plast->pnext == NULL) {
plast->pnext = pnode;
}
}
list->length++;
list->size += nlen + vlen + 1; /* 1 overhead for '=' */
return SPAS_NO_ERROR;
}
char *param_list_to_str(const SPAS_PARAM_LIST *list) {
int size = 0;
int pos = 0;
char *buf = NULL;
SPAS_PARAM_NODE *pnode = NULL;
if (list == NULL) {
return NULL;
}
if (list->length == 0) {
return (char *)_mem_alloc(1);
}
size = list->size + list->length - 1; /* overhead for '&' */
buf = (char *)_mem_alloc(size);
if (buf == NULL) {
return NULL;
}
pnode = list->phead;
if (pnode != NULL) {
sprintf(buf, "%s=%s", pnode->name, pnode->value);
pos += strlen(pnode->name) + strlen(pnode->value) + 1;
pnode = pnode->pnext;
}
while (pnode != NULL) {
sprintf(buf + pos, "&%s=%s", pnode->name, pnode->value);
pos += strlen(pnode->name) + strlen(pnode->value) + 2;
pnode = pnode->pnext;
}
return buf;
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,507 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "sha1.h"
#include <stddef.h>
#include <string.h>
#if USE_UNLOCKED_IO
# include "unlocked-io.h"
#endif
#ifdef __cplusplus
namespace rocketmqSignature {
#endif
#ifdef WORDS_BIGENDIAN
# define SWAP(n) (n)
#else
# define SWAP(n) \
(((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
#endif
#define BLOCKSIZE 4096
#if BLOCKSIZE % 64 != 0
# error "invalid BLOCKSIZE"
#endif
/* This array contains the bytes used to pad the buffer to the next
64-byte boundary. (RFC 1321, 3.1: Step 1) */
static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
/*!
* @fn void sha1_init_ctx (struct sha1_ctx *ctx)
*
* @brief initialize a context with start constants
*
* @details Take a pointer to a 160 bit block of data (five 32 bit ints) and
* initialize it to the start constants of the SHA1 algorithm. This
* must be called before using hash in the call to sha1_hash.
*
* @param[out] ctx pointer to a context to be initialized
*/
void
sha1_init_ctx (struct sha1_ctx *ctx)
{
ctx->A = 0x67452301;
ctx->B = 0xefcdab89;
ctx->C = 0x98badcfe;
ctx->D = 0x10325476;
ctx->E = 0xc3d2e1f0;
ctx->total[0] = ctx->total[1] = 0;
ctx->buflen = 0;
}
/*!
* @fn static __inline__ void set_uint32 (char *cp, uint32_t v)
*
* @brief Copy the 4 byte value from v into the memory location pointed to
by *cp
*
* @details Copy the 4 byte value from v into the memory location pointed to by
* *cp, If your architecture allows unaligned access this is equivalent
* to * (uint32_t *) cp = v
*
* @param[out] cp memory location to copy v into
* @param[in] v 4 byte value to be copied
*/
#ifdef WIN32
static _inline void
#else
static __inline__ void
#endif
set_uint32 (char *cp, uint32_t v)
{
memcpy (cp, &v, sizeof v);
}
/*!
* @fn void *sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf)
*
* @brief Put result from CTX in first 20 bytes following RESBUF
*
* @details Put result from CTX in first 20 bytes following RESBUF. The result
* must be in little endian byte order.
*
* @param[in] ctx context whose results will be copied
* @param[out] resbuf result of copies saved in little endian byte order
* @return resbuf
*/
void *
sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf)
{
char *r = (char*)resbuf;
set_uint32 (r + 0 * sizeof ctx->A, SWAP (ctx->A));
set_uint32 (r + 1 * sizeof ctx->B, SWAP (ctx->B));
set_uint32 (r + 2 * sizeof ctx->C, SWAP (ctx->C));
set_uint32 (r + 3 * sizeof ctx->D, SWAP (ctx->D));
set_uint32 (r + 4 * sizeof ctx->E, SWAP (ctx->E));
return resbuf;
}
/*!
* @fn void *sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf)
*
* @brief Process the remaining bytes in the internal buffer and write
the result to RESBUF.
*
* @details Process the remaining bytes in the internal buffer and the usual
* prolog according to the standard and write the result to RESBUF.
*
* @param[in] ctx context to be used
* @param[out] resbuf resultant SHA1 hash
* @return resultant SHA1 hash
*/
void *
sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf)
{
/* Take yet unprocessed bytes into account. */
uint32_t bytes = ctx->buflen;
size_t size = (bytes < 56) ? 64 / 4 : 64 * 2 / 4;
/* Now count remaining bytes. */
ctx->total[0] += bytes;
if (ctx->total[0] < bytes)
++ctx->total[1];
/* Put the 64-bit file length in *bits* at the end of the buffer. */
ctx->buffer[size - 2] = SWAP ((ctx->total[1] << 3) | (ctx->total[0] >> 29));
ctx->buffer[size - 1] = SWAP (ctx->total[0] << 3);
memcpy (&((char *) ctx->buffer)[bytes], fillbuf, (size - 2) * 4 - bytes);
/* Process last bytes. */
sha1_process_block (ctx->buffer, size * 4, ctx);
return sha1_read_ctx (ctx, resbuf);
}
/*
* @fn void *sha1_stream (FILE *stream, void *resblock)
*
* @brief Compute SHA1 message digest for A Stream.
*
* @details Compute SHA1 message digest for Stream. The
* result is always in little endian byte order, so that a byte-wise
* output yields to the wanted ASCII representation of the message
* digest.
*
* @param[in] stream message stream to be hashed
* @param[out] resblock resultant hash in little endian byte order
* @return resultant hash in little endian byte order
*/
int
sha1_stream (FILE *stream, void *resblock)
{
struct sha1_ctx ctx;
char buffer[BLOCKSIZE + 72];
size_t sum;
/* Initialize the computation context. */
sha1_init_ctx (&ctx);
/* Iterate over full file contents. */
while (1)
{
/* We read the file in blocks of BLOCKSIZE bytes. One call of the
computation function processes the whole buffer so that with the
next round of the loop another block can be read. */
size_t n;
sum = 0;
/* Read block. Take care for partial reads. */
while (1)
{
n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
sum += n;
if (sum == BLOCKSIZE)
break;
if (n == 0)
{
/* Check for the error flag IFF N == 0, so that we don't
exit the loop after a partial read due to e.g., EAGAIN
or EWOULDBLOCK. */
if (ferror (stream))
return 1;
goto process_partial_block;
}
/* We've read at least one byte, so ignore errors. But always
check for EOF, since feof may be true even though N > 0.
Otherwise, we could end up calling fread after EOF. */
if (feof (stream))
goto process_partial_block;
}
/* Process buffer with BLOCKSIZE bytes. Note that
BLOCKSIZE % 64 == 0
*/
sha1_process_block (buffer, BLOCKSIZE, &ctx);
}
process_partial_block:;
/* Process any remaining bytes. */
if (sum > 0)
sha1_process_bytes (buffer, sum, &ctx);
/* Construct result in desired memory. */
sha1_finish_ctx (&ctx, resblock);
return 0;
}
/*
* @fn void *sha1_buffer (const char *buffer, size_t len, void *resblock)
*
* @brief Compute SHA1 message digest for LEN bytes beginning at BUFFER.
*
* @details Compute SHA1 message digest for LEN bytes beginning at BUFFER. The
* result is always in little endian byte order, so that a byte-wise
* output yields to the wanted ASCII representation of the message
* digest.
*
* @param[in] buffer message to be hashed
* @param[in] len length of buffer
* @param[out] resblock resultant hash in little endian byte order
* @return resultant hash in little endian byte order
*/
void *
sha1_buffer (const char *buffer, size_t len, void *resblock)
{
struct sha1_ctx ctx;
/* Initialize the computation context. */
sha1_init_ctx (&ctx);
/* Process whole buffer but last len % 64 bytes. */
sha1_process_bytes (buffer, len, &ctx);
/* Put result in desired memory area. */
return sha1_finish_ctx (&ctx, resblock);
}
/*!
* @fn void sha1_process_bytes (const void *buffer, size_t len, struct sha1_ctx *ctx)
*
* @brief update the context for the next LEN bytes starting at BUFFER.
*
* @details Starting with the result of former calls of this function (or the
* initialization function) update the context for the next LEN bytes
* starting at BUFFER.
* It is NOT required that LEN is a multiple of 64.
*
* @param[in] buffer buffer used to update context values
* @param[in] len length of buffer
* @param[out] ctx context to be updated
*/
void
sha1_process_bytes (const void *buffer, size_t len, struct sha1_ctx *ctx)
{
/* When we already have some bits in our internal buffer concatenate
both inputs first. */
if (ctx->buflen != 0)
{
size_t left_over = ctx->buflen;
size_t add = 128 - left_over > len ? len : 128 - left_over;
memcpy (&((char *) ctx->buffer)[left_over], buffer, add);
ctx->buflen += add;
if (ctx->buflen > 64)
{
sha1_process_block (ctx->buffer, ctx->buflen & ~63, ctx);
ctx->buflen &= 63;
/* The regions in the following copy operation cannot overlap. */
memcpy (ctx->buffer,
&((char *) ctx->buffer)[(left_over + add) & ~63],
ctx->buflen);
}
buffer = (const char *) buffer + add;
len -= add;
}
/* Process available complete blocks. */
if (len >= 64)
{
#if !_STRING_ARCH_unaligned
# define alignof(type) offsetof (struct { char c; type x; }, x)
# define UNALIGNED_P(p) (((size_t) p) % alignof (uint32_t) != 0)
if (UNALIGNED_P (buffer))
while (len > 64)
{
sha1_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx);
buffer = (const char *) buffer + 64;
len -= 64;
}
else
#endif
{
sha1_process_block (buffer, len & ~63, ctx);
buffer = (const char *) buffer + (len & ~63);
len &= 63;
}
}
/* Move remaining bytes in internal buffer. */
if (len > 0)
{
size_t left_over = ctx->buflen;
memcpy (&((char *) ctx->buffer)[left_over], buffer, len);
left_over += len;
if (left_over >= 64)
{
sha1_process_block (ctx->buffer, 64, ctx);
left_over -= 64;
memcpy (ctx->buffer, &ctx->buffer[16], left_over);
}
ctx->buflen = left_over;
}
}
/* --- Code below is the primary difference between md5.c and sha1.c --- */
/* SHA1 round constants */
#define K1 0x5a827999
#define K2 0x6ed9eba1
#define K3 0x8f1bbcdc
#define K4 0xca62c1d6
/* Round functions. Note that F2 is the same as F4. */
#define F1(B,C,D) ( D ^ ( B & ( C ^ D ) ) )
#define F2(B,C,D) (B ^ C ^ D)
#define F3(B,C,D) ( ( B & C ) | ( D & ( B | C ) ) )
#define F4(B,C,D) (B ^ C ^ D)
/*!
* @fn void sha1_process_block (const void *buffer, size_t len, struct sha1_ctx *ctx)
*
* @brief Process LEN bytes of BUFFER, accumulating context into CTX.
*
* @details Process LEN bytes of BUFFER, accumulating context into CTX.
* It is assumed that LEN % 64 == 0.
* Most of this code comes from GnuPG's cipher/sha1.c.
*
* @param[in] buffer buffer to be processed
* @param[in] len length of buffer
* @param[out] ctx context used to accumulate results
*/
void
sha1_process_block (const void *buffer, size_t len, struct sha1_ctx *ctx)
{
const uint32_t *words = (const uint32_t*)buffer;
size_t nwords = len / sizeof (uint32_t);
const uint32_t *endp = words + nwords;
uint32_t x[16];
uint32_t a = ctx->A;
uint32_t b = ctx->B;
uint32_t c = ctx->C;
uint32_t d = ctx->D;
uint32_t e = ctx->E;
/* First increment the byte count. RFC 1321 specifies the possible
length of the file up to 2^64 bits. Here we only compute the
number of bytes. Do a double word increment. */
ctx->total[0] += len;
if (ctx->total[0] < len)
++ctx->total[1];
#define rol(x, n) (((x) << (n)) | ((uint32_t) (x) >> (32 - (n))))
#define M(I) ( tm = x[I&0x0f] ^ x[(I-14)&0x0f] \
^ x[(I-8)&0x0f] ^ x[(I-3)&0x0f] \
, (x[I&0x0f] = rol(tm, 1)) )
#define R(A,B,C,D,E,F,K,M) do { E += rol( A, 5 ) \
+ F( B, C, D ) \
+ K \
+ M; \
B = rol( B, 30 ); \
} while(0)
while (words < endp)
{
uint32_t tm;
int t;
for (t = 0; t < 16; t++)
{
x[t] = SWAP (*words);
words++;
}
R( a, b, c, d, e, F1, K1, x[ 0] );
R( e, a, b, c, d, F1, K1, x[ 1] );
R( d, e, a, b, c, F1, K1, x[ 2] );
R( c, d, e, a, b, F1, K1, x[ 3] );
R( b, c, d, e, a, F1, K1, x[ 4] );
R( a, b, c, d, e, F1, K1, x[ 5] );
R( e, a, b, c, d, F1, K1, x[ 6] );
R( d, e, a, b, c, F1, K1, x[ 7] );
R( c, d, e, a, b, F1, K1, x[ 8] );
R( b, c, d, e, a, F1, K1, x[ 9] );
R( a, b, c, d, e, F1, K1, x[10] );
R( e, a, b, c, d, F1, K1, x[11] );
R( d, e, a, b, c, F1, K1, x[12] );
R( c, d, e, a, b, F1, K1, x[13] );
R( b, c, d, e, a, F1, K1, x[14] );
R( a, b, c, d, e, F1, K1, x[15] );
R( e, a, b, c, d, F1, K1, M(16) );
R( d, e, a, b, c, F1, K1, M(17) );
R( c, d, e, a, b, F1, K1, M(18) );
R( b, c, d, e, a, F1, K1, M(19) );
R( a, b, c, d, e, F2, K2, M(20) );
R( e, a, b, c, d, F2, K2, M(21) );
R( d, e, a, b, c, F2, K2, M(22) );
R( c, d, e, a, b, F2, K2, M(23) );
R( b, c, d, e, a, F2, K2, M(24) );
R( a, b, c, d, e, F2, K2, M(25) );
R( e, a, b, c, d, F2, K2, M(26) );
R( d, e, a, b, c, F2, K2, M(27) );
R( c, d, e, a, b, F2, K2, M(28) );
R( b, c, d, e, a, F2, K2, M(29) );
R( a, b, c, d, e, F2, K2, M(30) );
R( e, a, b, c, d, F2, K2, M(31) );
R( d, e, a, b, c, F2, K2, M(32) );
R( c, d, e, a, b, F2, K2, M(33) );
R( b, c, d, e, a, F2, K2, M(34) );
R( a, b, c, d, e, F2, K2, M(35) );
R( e, a, b, c, d, F2, K2, M(36) );
R( d, e, a, b, c, F2, K2, M(37) );
R( c, d, e, a, b, F2, K2, M(38) );
R( b, c, d, e, a, F2, K2, M(39) );
R( a, b, c, d, e, F3, K3, M(40) );
R( e, a, b, c, d, F3, K3, M(41) );
R( d, e, a, b, c, F3, K3, M(42) );
R( c, d, e, a, b, F3, K3, M(43) );
R( b, c, d, e, a, F3, K3, M(44) );
R( a, b, c, d, e, F3, K3, M(45) );
R( e, a, b, c, d, F3, K3, M(46) );
R( d, e, a, b, c, F3, K3, M(47) );
R( c, d, e, a, b, F3, K3, M(48) );
R( b, c, d, e, a, F3, K3, M(49) );
R( a, b, c, d, e, F3, K3, M(50) );
R( e, a, b, c, d, F3, K3, M(51) );
R( d, e, a, b, c, F3, K3, M(52) );
R( c, d, e, a, b, F3, K3, M(53) );
R( b, c, d, e, a, F3, K3, M(54) );
R( a, b, c, d, e, F3, K3, M(55) );
R( e, a, b, c, d, F3, K3, M(56) );
R( d, e, a, b, c, F3, K3, M(57) );
R( c, d, e, a, b, F3, K3, M(58) );
R( b, c, d, e, a, F3, K3, M(59) );
R( a, b, c, d, e, F4, K4, M(60) );
R( e, a, b, c, d, F4, K4, M(61) );
R( d, e, a, b, c, F4, K4, M(62) );
R( c, d, e, a, b, F4, K4, M(63) );
R( b, c, d, e, a, F4, K4, M(64) );
R( a, b, c, d, e, F4, K4, M(65) );
R( e, a, b, c, d, F4, K4, M(66) );
R( d, e, a, b, c, F4, K4, M(67) );
R( c, d, e, a, b, F4, K4, M(68) );
R( b, c, d, e, a, F4, K4, M(69) );
R( a, b, c, d, e, F4, K4, M(70) );
R( e, a, b, c, d, F4, K4, M(71) );
R( d, e, a, b, c, F4, K4, M(72) );
R( c, d, e, a, b, F4, K4, M(73) );
R( b, c, d, e, a, F4, K4, M(74) );
R( a, b, c, d, e, F4, K4, M(75) );
R( e, a, b, c, d, F4, K4, M(76) );
R( d, e, a, b, c, F4, K4, M(77) );
R( c, d, e, a, b, F4, K4, M(78) );
R( b, c, d, e, a, F4, K4, M(79) );
a = ctx->A += a;
b = ctx->B += b;
c = ctx->C += c;
d = ctx->D += d;
e = ctx->E += e;
}
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,559 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "sha256.h"
#include <stddef.h>
#include <string.h>
#if USE_UNLOCKED_IO
# include "unlocked-io.h"
#endif
#ifdef __cplusplus
namespace rocketmqSignature {
#endif
#ifdef WORDS_BIGENDIAN
# define SWAP(n) (n)
#else
# define SWAP(n) \
(((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
#endif
#define BLOCKSIZE 4096
#if BLOCKSIZE % 64 != 0
# error "invalid BLOCKSIZE"
#endif
/* This array contains the bytes used to pad the buffer to the next
64-byte boundary. */
static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
/*
Takes a pointer to a 256 bit block of data (eight 32 bit ints) and
intializes it to the start constants of the SHA256 algorithm. This
must be called before using hash in the call to sha256_hash
*/
void
sha256_init_ctx (struct sha256_ctx *ctx)
{
ctx->state[0] = 0x6a09e667UL;
ctx->state[1] = 0xbb67ae85UL;
ctx->state[2] = 0x3c6ef372UL;
ctx->state[3] = 0xa54ff53aUL;
ctx->state[4] = 0x510e527fUL;
ctx->state[5] = 0x9b05688cUL;
ctx->state[6] = 0x1f83d9abUL;
ctx->state[7] = 0x5be0cd19UL;
ctx->total[0] = ctx->total[1] = 0;
ctx->buflen = 0;
}
void
sha224_init_ctx (struct sha256_ctx *ctx)
{
ctx->state[0] = 0xc1059ed8UL;
ctx->state[1] = 0x367cd507UL;
ctx->state[2] = 0x3070dd17UL;
ctx->state[3] = 0xf70e5939UL;
ctx->state[4] = 0xffc00b31UL;
ctx->state[5] = 0x68581511UL;
ctx->state[6] = 0x64f98fa7UL;
ctx->state[7] = 0xbefa4fa4UL;
ctx->total[0] = ctx->total[1] = 0;
ctx->buflen = 0;
}
/* Copy the value from v into the memory location pointed to by *cp,
If your architecture allows unaligned access this is equivalent to
* (uint32_t *) cp = v */
#ifdef WIN32
static _inline void
#else
static __inline__ void
#endif
set_uint32 (char *cp, uint32_t v)
{
memcpy (cp, &v, sizeof v);
}
/* Put result from CTX in first 32 bytes following RESBUF. The result
must be in little endian byte order. */
void *
sha256_read_ctx (const struct sha256_ctx *ctx, void *resbuf)
{
int i;
char *r = (char*)resbuf;
for (i = 0; i < 8; i++)
set_uint32 (r + i * sizeof ctx->state[0], SWAP (ctx->state[i]));
return resbuf;
}
void *
sha224_read_ctx (const struct sha256_ctx *ctx, void *resbuf)
{
int i;
char *r = (char*)resbuf;
for (i = 0; i < 7; i++)
set_uint32 (r + i * sizeof ctx->state[0], SWAP (ctx->state[i]));
return resbuf;
}
/* Process the remaining bytes in the internal buffer and the usual
prolog according to the standard and write the result to RESBUF. */
static void
sha256_conclude_ctx (struct sha256_ctx *ctx)
{
/* Take yet unprocessed bytes into account. */
size_t bytes = ctx->buflen;
size_t size = (bytes < 56) ? 64 / 4 : 64 * 2 / 4;
/* Now count remaining bytes. */
ctx->total[0] += bytes;
if (ctx->total[0] < bytes)
++ctx->total[1];
/* Put the 64-bit file length in *bits* at the end of the buffer.
Use set_uint32 rather than a simple assignment, to avoid risk of
unaligned access. */
set_uint32 ((char *) &ctx->buffer[size - 2],
SWAP ((ctx->total[1] << 3) | (ctx->total[0] >> 29)));
set_uint32 ((char *) &ctx->buffer[size - 1],
SWAP (ctx->total[0] << 3));
memcpy (&((char *) ctx->buffer)[bytes], fillbuf, (size - 2) * 4 - bytes);
/* Process last bytes. */
sha256_process_block (ctx->buffer, size * 4, ctx);
}
void *
sha256_finish_ctx (struct sha256_ctx *ctx, void *resbuf)
{
sha256_conclude_ctx (ctx);
return sha256_read_ctx (ctx, resbuf);
}
void *
sha224_finish_ctx (struct sha256_ctx *ctx, void *resbuf)
{
sha256_conclude_ctx (ctx);
return sha224_read_ctx (ctx, resbuf);
}
/* Compute SHA256 message digest for bytes read from STREAM. The
resulting message digest number will be written into the 32 bytes
beginning at RESBLOCK. */
int
sha256_stream (FILE *stream, void *resblock)
{
struct sha256_ctx ctx;
char buffer[BLOCKSIZE + 72];
size_t sum;
/* Initialize the computation context. */
sha256_init_ctx (&ctx);
/* Iterate over full file contents. */
while (1)
{
/* We read the file in blocks of BLOCKSIZE bytes. One call of the
computation function processes the whole buffer so that with the
next round of the loop another block can be read. */
size_t n;
sum = 0;
/* Read block. Take care for partial reads. */
while (1)
{
n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
sum += n;
if (sum == BLOCKSIZE)
break;
if (n == 0)
{
/* Check for the error flag IFF N == 0, so that we don't
exit the loop after a partial read due to e.g., EAGAIN
or EWOULDBLOCK. */
if (ferror (stream))
return 1;
goto process_partial_block;
}
/* We've read at least one byte, so ignore errors. But always
check for EOF, since feof may be true even though N > 0.
Otherwise, we could end up calling fread after EOF. */
if (feof (stream))
goto process_partial_block;
}
/* Process buffer with BLOCKSIZE bytes. Note that
BLOCKSIZE % 64 == 0
*/
sha256_process_block (buffer, BLOCKSIZE, &ctx);
}
process_partial_block:;
/* Process any remaining bytes. */
if (sum > 0)
sha256_process_bytes (buffer, sum, &ctx);
/* Construct result in desired memory. */
sha256_finish_ctx (&ctx, resblock);
return 0;
}
/* FIXME: Avoid code duplication */
int
sha224_stream (FILE *stream, void *resblock)
{
struct sha256_ctx ctx;
char buffer[BLOCKSIZE + 72];
size_t sum;
/* Initialize the computation context. */
sha224_init_ctx (&ctx);
/* Iterate over full file contents. */
while (1)
{
/* We read the file in blocks of BLOCKSIZE bytes. One call of the
computation function processes the whole buffer so that with the
next round of the loop another block can be read. */
size_t n;
sum = 0;
/* Read block. Take care for partial reads. */
while (1)
{
n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
sum += n;
if (sum == BLOCKSIZE)
break;
if (n == 0)
{
/* Check for the error flag IFF N == 0, so that we don't
exit the loop after a partial read due to e.g., EAGAIN
or EWOULDBLOCK. */
if (ferror (stream))
return 1;
goto process_partial_block;
}
/* We've read at least one byte, so ignore errors. But always
check for EOF, since feof may be true even though N > 0.
Otherwise, we could end up calling fread after EOF. */
if (feof (stream))
goto process_partial_block;
}
/* Process buffer with BLOCKSIZE bytes. Note that
BLOCKSIZE % 64 == 0
*/
sha256_process_block (buffer, BLOCKSIZE, &ctx);
}
process_partial_block:;
/* Process any remaining bytes. */
if (sum > 0)
sha256_process_bytes (buffer, sum, &ctx);
/* Construct result in desired memory. */
sha224_finish_ctx (&ctx, resblock);
return 0;
}
/* Compute SHA512 message digest for LEN bytes beginning at BUFFER. The
result is always in little endian byte order, so that a byte-wise
output yields to the wanted ASCII representation of the message
digest. */
void *
sha256_buffer (const char *buffer, size_t len, void *resblock)
{
struct sha256_ctx ctx;
/* Initialize the computation context. */
sha256_init_ctx (&ctx);
/* Process whole buffer but last len % 64 bytes. */
sha256_process_bytes (buffer, len, &ctx);
/* Put result in desired memory area. */
return sha256_finish_ctx (&ctx, resblock);
}
void *
sha224_buffer (const char *buffer, size_t len, void *resblock)
{
struct sha256_ctx ctx;
/* Initialize the computation context. */
sha224_init_ctx (&ctx);
/* Process whole buffer but last len % 64 bytes. */
sha256_process_bytes (buffer, len, &ctx);
/* Put result in desired memory area. */
return sha224_finish_ctx (&ctx, resblock);
}
void
sha256_process_bytes (const void *buffer, size_t len, struct sha256_ctx *ctx)
{
/* When we already have some bits in our internal buffer concatenate
both inputs first. */
if (ctx->buflen != 0)
{
size_t left_over = ctx->buflen;
size_t add = 128 - left_over > len ? len : 128 - left_over;
memcpy (&((char *) ctx->buffer)[left_over], buffer, add);
ctx->buflen += add;
if (ctx->buflen > 64)
{
sha256_process_block (ctx->buffer, ctx->buflen & ~63, ctx);
ctx->buflen &= 63;
/* The regions in the following copy operation cannot overlap. */
memcpy (ctx->buffer,
&((char *) ctx->buffer)[(left_over + add) & ~63],
ctx->buflen);
}
buffer = (const char *) buffer + add;
len -= add;
}
/* Process available complete blocks. */
if (len >= 64)
{
#if !_STRING_ARCH_unaligned
# define alignof(type) offsetof (struct { char c; type x; }, x)
# define UNALIGNED_P(p) (((size_t) p) % alignof (uint32_t) != 0)
if (UNALIGNED_P (buffer))
while (len > 64)
{
sha256_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx);
buffer = (const char *) buffer + 64;
len -= 64;
}
else
#endif
{
sha256_process_block (buffer, len & ~63, ctx);
buffer = (const char *) buffer + (len & ~63);
len &= 63;
}
}
/* Move remaining bytes in internal buffer. */
if (len > 0)
{
size_t left_over = ctx->buflen;
memcpy (&((char *) ctx->buffer)[left_over], buffer, len);
left_over += len;
if (left_over >= 64)
{
sha256_process_block (ctx->buffer, 64, ctx);
left_over -= 64;
memcpy (ctx->buffer, &ctx->buffer[16], left_over);
}
ctx->buflen = left_over;
}
}
/* --- Code below is the primary difference between sha1.c and sha256.c --- */
/* SHA256 round constants */
#define K(I) sha256_round_constants[I]
static const uint32_t sha256_round_constants[64] = {
0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL,
};
/* Round functions. */
#define F2(A,B,C) ( ( A & B ) | ( C & ( A | B ) ) )
#define F1(E,F,G) ( G ^ ( E & ( F ^ G ) ) )
/* Process LEN bytes of BUFFER, accumulating context into CTX.
It is assumed that LEN % 64 == 0.
Most of this code comes from GnuPG's cipher/sha1.c. */
void
sha256_process_block (const void *buffer, size_t len, struct sha256_ctx *ctx)
{
const uint32_t *words = (const uint32_t *)buffer;
size_t nwords = len / sizeof (uint32_t);
const uint32_t *endp = words + nwords;
uint32_t x[16];
uint32_t a = ctx->state[0];
uint32_t b = ctx->state[1];
uint32_t c = ctx->state[2];
uint32_t d = ctx->state[3];
uint32_t e = ctx->state[4];
uint32_t f = ctx->state[5];
uint32_t g = ctx->state[6];
uint32_t h = ctx->state[7];
/* First increment the byte count. FIPS PUB 180-2 specifies the possible
length of the file up to 2^64 bits. Here we only compute the
number of bytes. Do a double word increment. */
ctx->total[0] += len;
if (ctx->total[0] < len)
++ctx->total[1];
#define rol(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
#define S0(x) (rol(x,25)^rol(x,14)^(x>>3))
#define S1(x) (rol(x,15)^rol(x,13)^(x>>10))
#define SS0(x) (rol(x,30)^rol(x,19)^rol(x,10))
#define SS1(x) (rol(x,26)^rol(x,21)^rol(x,7))
#define M(I) ( tm = S1(x[(I-2)&0x0f]) + x[(I-7)&0x0f] \
+ S0(x[(I-15)&0x0f]) + x[I&0x0f] \
, x[I&0x0f] = tm )
#define R(A,B,C,D,E,F,G,H,K,M) do { t0 = SS0(A) + F2(A,B,C); \
t1 = H + SS1(E) \
+ F1(E,F,G) \
+ K \
+ M; \
D += t1; H = t0 + t1; \
} while(0)
while (words < endp)
{
uint32_t tm;
uint32_t t0, t1;
int t;
/* FIXME: see sha1.c for a better implementation. */
for (t = 0; t < 16; t++)
{
x[t] = SWAP (*words);
words++;
}
R( a, b, c, d, e, f, g, h, K( 0), x[ 0] );
R( h, a, b, c, d, e, f, g, K( 1), x[ 1] );
R( g, h, a, b, c, d, e, f, K( 2), x[ 2] );
R( f, g, h, a, b, c, d, e, K( 3), x[ 3] );
R( e, f, g, h, a, b, c, d, K( 4), x[ 4] );
R( d, e, f, g, h, a, b, c, K( 5), x[ 5] );
R( c, d, e, f, g, h, a, b, K( 6), x[ 6] );
R( b, c, d, e, f, g, h, a, K( 7), x[ 7] );
R( a, b, c, d, e, f, g, h, K( 8), x[ 8] );
R( h, a, b, c, d, e, f, g, K( 9), x[ 9] );
R( g, h, a, b, c, d, e, f, K(10), x[10] );
R( f, g, h, a, b, c, d, e, K(11), x[11] );
R( e, f, g, h, a, b, c, d, K(12), x[12] );
R( d, e, f, g, h, a, b, c, K(13), x[13] );
R( c, d, e, f, g, h, a, b, K(14), x[14] );
R( b, c, d, e, f, g, h, a, K(15), x[15] );
R( a, b, c, d, e, f, g, h, K(16), M(16) );
R( h, a, b, c, d, e, f, g, K(17), M(17) );
R( g, h, a, b, c, d, e, f, K(18), M(18) );
R( f, g, h, a, b, c, d, e, K(19), M(19) );
R( e, f, g, h, a, b, c, d, K(20), M(20) );
R( d, e, f, g, h, a, b, c, K(21), M(21) );
R( c, d, e, f, g, h, a, b, K(22), M(22) );
R( b, c, d, e, f, g, h, a, K(23), M(23) );
R( a, b, c, d, e, f, g, h, K(24), M(24) );
R( h, a, b, c, d, e, f, g, K(25), M(25) );
R( g, h, a, b, c, d, e, f, K(26), M(26) );
R( f, g, h, a, b, c, d, e, K(27), M(27) );
R( e, f, g, h, a, b, c, d, K(28), M(28) );
R( d, e, f, g, h, a, b, c, K(29), M(29) );
R( c, d, e, f, g, h, a, b, K(30), M(30) );
R( b, c, d, e, f, g, h, a, K(31), M(31) );
R( a, b, c, d, e, f, g, h, K(32), M(32) );
R( h, a, b, c, d, e, f, g, K(33), M(33) );
R( g, h, a, b, c, d, e, f, K(34), M(34) );
R( f, g, h, a, b, c, d, e, K(35), M(35) );
R( e, f, g, h, a, b, c, d, K(36), M(36) );
R( d, e, f, g, h, a, b, c, K(37), M(37) );
R( c, d, e, f, g, h, a, b, K(38), M(38) );
R( b, c, d, e, f, g, h, a, K(39), M(39) );
R( a, b, c, d, e, f, g, h, K(40), M(40) );
R( h, a, b, c, d, e, f, g, K(41), M(41) );
R( g, h, a, b, c, d, e, f, K(42), M(42) );
R( f, g, h, a, b, c, d, e, K(43), M(43) );
R( e, f, g, h, a, b, c, d, K(44), M(44) );
R( d, e, f, g, h, a, b, c, K(45), M(45) );
R( c, d, e, f, g, h, a, b, K(46), M(46) );
R( b, c, d, e, f, g, h, a, K(47), M(47) );
R( a, b, c, d, e, f, g, h, K(48), M(48) );
R( h, a, b, c, d, e, f, g, K(49), M(49) );
R( g, h, a, b, c, d, e, f, K(50), M(50) );
R( f, g, h, a, b, c, d, e, K(51), M(51) );
R( e, f, g, h, a, b, c, d, K(52), M(52) );
R( d, e, f, g, h, a, b, c, K(53), M(53) );
R( c, d, e, f, g, h, a, b, K(54), M(54) );
R( b, c, d, e, f, g, h, a, K(55), M(55) );
R( a, b, c, d, e, f, g, h, K(56), M(56) );
R( h, a, b, c, d, e, f, g, K(57), M(57) );
R( g, h, a, b, c, d, e, f, K(58), M(58) );
R( f, g, h, a, b, c, d, e, K(59), M(59) );
R( e, f, g, h, a, b, c, d, K(60), M(60) );
R( d, e, f, g, h, a, b, c, K(61), M(61) );
R( c, d, e, f, g, h, a, b, K(62), M(62) );
R( b, c, d, e, f, g, h, a, K(63), M(63) );
a = ctx->state[0] += a;
b = ctx->state[1] += b;
c = ctx->state[2] += c;
d = ctx->state[3] += d;
e = ctx->state[4] += e;
f = ctx->state[5] += f;
g = ctx->state[6] += g;
h = ctx->state[7] += h;
}
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,609 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "sha512.h"
#include <stddef.h>
#include <string.h>
#if USE_UNLOCKED_IO
# include "unlocked-io.h"
#endif
#ifdef __cplusplus
namespace rocketmqSignature{
#endif
#ifdef WORDS_BIGENDIAN
# define SWAP(n) (n)
#else
# define SWAP(n) \
u64or (u64or (u64or (u64shl (n, 56), \
u64shl (u64and (n, u64lo (0x0000ff00)), 40)), \
u64or (u64shl (u64and (n, u64lo (0x00ff0000)), 24), \
u64shl (u64and (n, u64lo (0xff000000)), 8))), \
u64or (u64or (u64and (u64shr (n, 8), u64lo (0xff000000)), \
u64and (u64shr (n, 24), u64lo (0x00ff0000))), \
u64or (u64and (u64shr (n, 40), u64lo (0x0000ff00)), \
u64shr (n, 56))))
#endif
#define BLOCKSIZE 4096
#if BLOCKSIZE % 128 != 0
# error "invalid BLOCKSIZE"
#endif
/* This array contains the bytes used to pad the buffer to the next
128-byte boundary. */
static const unsigned char fillbuf[128] = { 0x80, 0 /* , 0, 0, ... */ };
/*
Takes a pointer to a 512 bit block of data (eight 64 bit ints) and
intializes it to the start constants of the SHA512 algorithm. This
must be called before using hash in the call to sha512_hash
*/
void
sha512_init_ctx (struct sha512_ctx *ctx)
{
ctx->state[0] = u64hilo (0x6a09e667, 0xf3bcc908);
ctx->state[1] = u64hilo (0xbb67ae85, 0x84caa73b);
ctx->state[2] = u64hilo (0x3c6ef372, 0xfe94f82b);
ctx->state[3] = u64hilo (0xa54ff53a, 0x5f1d36f1);
ctx->state[4] = u64hilo (0x510e527f, 0xade682d1);
ctx->state[5] = u64hilo (0x9b05688c, 0x2b3e6c1f);
ctx->state[6] = u64hilo (0x1f83d9ab, 0xfb41bd6b);
ctx->state[7] = u64hilo (0x5be0cd19, 0x137e2179);
ctx->total[0] = ctx->total[1] = u64lo (0);
ctx->buflen = 0;
}
void
sha384_init_ctx (struct sha512_ctx *ctx)
{
ctx->state[0] = u64hilo (0xcbbb9d5d, 0xc1059ed8);
ctx->state[1] = u64hilo (0x629a292a, 0x367cd507);
ctx->state[2] = u64hilo (0x9159015a, 0x3070dd17);
ctx->state[3] = u64hilo (0x152fecd8, 0xf70e5939);
ctx->state[4] = u64hilo (0x67332667, 0xffc00b31);
ctx->state[5] = u64hilo (0x8eb44a87, 0x68581511);
ctx->state[6] = u64hilo (0xdb0c2e0d, 0x64f98fa7);
ctx->state[7] = u64hilo (0x47b5481d, 0xbefa4fa4);
ctx->total[0] = ctx->total[1] = u64lo (0);
ctx->buflen = 0;
}
/* Copy the value from V into the memory location pointed to by *CP,
If your architecture allows unaligned access, this is equivalent to
* (__typeof__ (v) *) cp = v */
#ifdef WIN32
static _inline void
#else
static __inline__ void
#endif
set_uint64 (char *cp, u64 v)
{
memcpy (cp, &v, sizeof v);
}
/* Put result from CTX in first 64 bytes following RESBUF.
The result must be in little endian byte order. */
void *
sha512_read_ctx (const struct sha512_ctx *ctx, void *resbuf)
{
int i;
char *r = (char*)resbuf;
for (i = 0; i < 8; i++)
set_uint64 (r + i * sizeof ctx->state[0], SWAP (ctx->state[i]));
return resbuf;
}
void *
sha384_read_ctx (const struct sha512_ctx *ctx, void *resbuf)
{
int i;
char *r = (char*)resbuf;
for (i = 0; i < 6; i++)
set_uint64 (r + i * sizeof ctx->state[0], SWAP (ctx->state[i]));
return resbuf;
}
/* Process the remaining bytes in the internal buffer and the usual
prolog according to the standard and write the result to RESBUF. */
static void
sha512_conclude_ctx (struct sha512_ctx *ctx)
{
/* Take yet unprocessed bytes into account. */
size_t bytes = ctx->buflen;
size_t size = (bytes < 112) ? 128 / 8 : 128 * 2 / 8;
/* Now count remaining bytes. */
ctx->total[0] = u64plus (ctx->total[0], u64lo (bytes));
if (u64lt (ctx->total[0], u64lo (bytes)))
ctx->total[1] = u64plus (ctx->total[1], u64lo (1));
/* Put the 128-bit file length in *bits* at the end of the buffer.
Use set_uint64 rather than a simple assignment, to avoid risk of
unaligned access. */
set_uint64 ((char *) &ctx->buffer[size - 2],
SWAP (u64or (u64shl (ctx->total[1], 3),
u64shr (ctx->total[0], 61))));
set_uint64 ((char *) &ctx->buffer[size - 1],
SWAP (u64shl (ctx->total[0], 3)));
memcpy (&((char *) ctx->buffer)[bytes], fillbuf, (size - 2) * 8 - bytes);
/* Process last bytes. */
sha512_process_block (ctx->buffer, size * 8, ctx);
}
void *
sha512_finish_ctx (struct sha512_ctx *ctx, void *resbuf)
{
sha512_conclude_ctx (ctx);
return sha512_read_ctx (ctx, resbuf);
}
void *
sha384_finish_ctx (struct sha512_ctx *ctx, void *resbuf)
{
sha512_conclude_ctx (ctx);
return sha384_read_ctx (ctx, resbuf);
}
/* Compute SHA512 message digest for bytes read from STREAM. The
resulting message digest number will be written into the 64 bytes
beginning at RESBLOCK. */
int
sha512_stream (FILE *stream, void *resblock)
{
struct sha512_ctx ctx;
char buffer[BLOCKSIZE + 72];
size_t sum;
/* Initialize the computation context. */
sha512_init_ctx (&ctx);
/* Iterate over full file contents. */
while (1)
{
/* We read the file in blocks of BLOCKSIZE bytes. One call of the
computation function processes the whole buffer so that with the
next round of the loop another block can be read. */
size_t n;
sum = 0;
/* Read block. Take care for partial reads. */
while (1)
{
n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
sum += n;
if (sum == BLOCKSIZE)
break;
if (n == 0)
{
/* Check for the error flag IFF N == 0, so that we don't
exit the loop after a partial read due to e.g., EAGAIN
or EWOULDBLOCK. */
if (ferror (stream))
return 1;
goto process_partial_block;
}
/* We've read at least one byte, so ignore errors. But always
check for EOF, since feof may be true even though N > 0.
Otherwise, we could end up calling fread after EOF. */
if (feof (stream))
goto process_partial_block;
}
/* Process buffer with BLOCKSIZE bytes. Note that
BLOCKSIZE % 128 == 0
*/
sha512_process_block (buffer, BLOCKSIZE, &ctx);
}
process_partial_block:;
/* Process any remaining bytes. */
if (sum > 0)
sha512_process_bytes (buffer, sum, &ctx);
/* Construct result in desired memory. */
sha512_finish_ctx (&ctx, resblock);
return 0;
}
/* FIXME: Avoid code duplication */
int
sha384_stream (FILE *stream, void *resblock)
{
struct sha512_ctx ctx;
char buffer[BLOCKSIZE + 72];
size_t sum;
/* Initialize the computation context. */
sha384_init_ctx (&ctx);
/* Iterate over full file contents. */
while (1)
{
/* We read the file in blocks of BLOCKSIZE bytes. One call of the
computation function processes the whole buffer so that with the
next round of the loop another block can be read. */
size_t n;
sum = 0;
/* Read block. Take care for partial reads. */
while (1)
{
n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
sum += n;
if (sum == BLOCKSIZE)
break;
if (n == 0)
{
/* Check for the error flag IFF N == 0, so that we don't
exit the loop after a partial read due to e.g., EAGAIN
or EWOULDBLOCK. */
if (ferror (stream))
return 1;
goto process_partial_block;
}
/* We've read at least one byte, so ignore errors. But always
check for EOF, since feof may be true even though N > 0.
Otherwise, we could end up calling fread after EOF. */
if (feof (stream))
goto process_partial_block;
}
/* Process buffer with BLOCKSIZE bytes. Note that
BLOCKSIZE % 128 == 0
*/
sha512_process_block (buffer, BLOCKSIZE, &ctx);
}
process_partial_block:;
/* Process any remaining bytes. */
if (sum > 0)
sha512_process_bytes (buffer, sum, &ctx);
/* Construct result in desired memory. */
sha384_finish_ctx (&ctx, resblock);
return 0;
}
/* Compute SHA512 message digest for LEN bytes beginning at BUFFER. The
result is always in little endian byte order, so that a byte-wise
output yields to the wanted ASCII representation of the message
digest. */
void *
sha512_buffer (const char *buffer, size_t len, void *resblock)
{
struct sha512_ctx ctx;
/* Initialize the computation context. */
sha512_init_ctx (&ctx);
/* Process whole buffer but last len % 128 bytes. */
sha512_process_bytes (buffer, len, &ctx);
/* Put result in desired memory area. */
return sha512_finish_ctx (&ctx, resblock);
}
void *
sha384_buffer (const char *buffer, size_t len, void *resblock)
{
struct sha512_ctx ctx;
/* Initialize the computation context. */
sha384_init_ctx (&ctx);
/* Process whole buffer but last len % 128 bytes. */
sha512_process_bytes (buffer, len, &ctx);
/* Put result in desired memory area. */
return sha384_finish_ctx (&ctx, resblock);
}
void
sha512_process_bytes (const void *buffer, size_t len, struct sha512_ctx *ctx)
{
/* When we already have some bits in our internal buffer concatenate
both inputs first. */
if (ctx->buflen != 0)
{
size_t left_over = ctx->buflen;
size_t add = 256 - left_over > len ? len : 256 - left_over;
memcpy (&((char *) ctx->buffer)[left_over], buffer, add);
ctx->buflen += add;
if (ctx->buflen > 128)
{
sha512_process_block (ctx->buffer, ctx->buflen & ~127, ctx);
ctx->buflen &= 127;
/* The regions in the following copy operation cannot overlap. */
memcpy (ctx->buffer,
&((char *) ctx->buffer)[(left_over + add) & ~127],
ctx->buflen);
}
buffer = (const char *) buffer + add;
len -= add;
}
/* Process available complete blocks. */
if (len >= 128)
{
#if !_STRING_ARCH_unaligned
# define alignof(type) offsetof (struct { char c; type x; }, x)
# define UNALIGNED_P(p) (((size_t) p) % alignof (u64) != 0)
if (UNALIGNED_P (buffer))
while (len > 128)
{
sha512_process_block (memcpy (ctx->buffer, buffer, 128), 128, ctx);
buffer = (const char *) buffer + 128;
len -= 128;
}
else
#endif
{
sha512_process_block (buffer, len & ~127, ctx);
buffer = (const char *) buffer + (len & ~127);
len &= 127;
}
}
/* Move remaining bytes in internal buffer. */
if (len > 0)
{
size_t left_over = ctx->buflen;
memcpy (&((char *) ctx->buffer)[left_over], buffer, len);
left_over += len;
if (left_over >= 128)
{
sha512_process_block (ctx->buffer, 128, ctx);
left_over -= 128;
memcpy (ctx->buffer, &ctx->buffer[16], left_over);
}
ctx->buflen = left_over;
}
}
/* --- Code below is the primary difference between sha1.c and sha512.c --- */
/* SHA512 round constants */
#define K(I) sha512_round_constants[I]
static u64 const sha512_round_constants[80] = {
u64init (0x428a2f98, 0xd728ae22), u64init (0x71374491, 0x23ef65cd),
u64init (0xb5c0fbcf, 0xec4d3b2f), u64init (0xe9b5dba5, 0x8189dbbc),
u64init (0x3956c25b, 0xf348b538), u64init (0x59f111f1, 0xb605d019),
u64init (0x923f82a4, 0xaf194f9b), u64init (0xab1c5ed5, 0xda6d8118),
u64init (0xd807aa98, 0xa3030242), u64init (0x12835b01, 0x45706fbe),
u64init (0x243185be, 0x4ee4b28c), u64init (0x550c7dc3, 0xd5ffb4e2),
u64init (0x72be5d74, 0xf27b896f), u64init (0x80deb1fe, 0x3b1696b1),
u64init (0x9bdc06a7, 0x25c71235), u64init (0xc19bf174, 0xcf692694),
u64init (0xe49b69c1, 0x9ef14ad2), u64init (0xefbe4786, 0x384f25e3),
u64init (0x0fc19dc6, 0x8b8cd5b5), u64init (0x240ca1cc, 0x77ac9c65),
u64init (0x2de92c6f, 0x592b0275), u64init (0x4a7484aa, 0x6ea6e483),
u64init (0x5cb0a9dc, 0xbd41fbd4), u64init (0x76f988da, 0x831153b5),
u64init (0x983e5152, 0xee66dfab), u64init (0xa831c66d, 0x2db43210),
u64init (0xb00327c8, 0x98fb213f), u64init (0xbf597fc7, 0xbeef0ee4),
u64init (0xc6e00bf3, 0x3da88fc2), u64init (0xd5a79147, 0x930aa725),
u64init (0x06ca6351, 0xe003826f), u64init (0x14292967, 0x0a0e6e70),
u64init (0x27b70a85, 0x46d22ffc), u64init (0x2e1b2138, 0x5c26c926),
u64init (0x4d2c6dfc, 0x5ac42aed), u64init (0x53380d13, 0x9d95b3df),
u64init (0x650a7354, 0x8baf63de), u64init (0x766a0abb, 0x3c77b2a8),
u64init (0x81c2c92e, 0x47edaee6), u64init (0x92722c85, 0x1482353b),
u64init (0xa2bfe8a1, 0x4cf10364), u64init (0xa81a664b, 0xbc423001),
u64init (0xc24b8b70, 0xd0f89791), u64init (0xc76c51a3, 0x0654be30),
u64init (0xd192e819, 0xd6ef5218), u64init (0xd6990624, 0x5565a910),
u64init (0xf40e3585, 0x5771202a), u64init (0x106aa070, 0x32bbd1b8),
u64init (0x19a4c116, 0xb8d2d0c8), u64init (0x1e376c08, 0x5141ab53),
u64init (0x2748774c, 0xdf8eeb99), u64init (0x34b0bcb5, 0xe19b48a8),
u64init (0x391c0cb3, 0xc5c95a63), u64init (0x4ed8aa4a, 0xe3418acb),
u64init (0x5b9cca4f, 0x7763e373), u64init (0x682e6ff3, 0xd6b2b8a3),
u64init (0x748f82ee, 0x5defb2fc), u64init (0x78a5636f, 0x43172f60),
u64init (0x84c87814, 0xa1f0ab72), u64init (0x8cc70208, 0x1a6439ec),
u64init (0x90befffa, 0x23631e28), u64init (0xa4506ceb, 0xde82bde9),
u64init (0xbef9a3f7, 0xb2c67915), u64init (0xc67178f2, 0xe372532b),
u64init (0xca273ece, 0xea26619c), u64init (0xd186b8c7, 0x21c0c207),
u64init (0xeada7dd6, 0xcde0eb1e), u64init (0xf57d4f7f, 0xee6ed178),
u64init (0x06f067aa, 0x72176fba), u64init (0x0a637dc5, 0xa2c898a6),
u64init (0x113f9804, 0xbef90dae), u64init (0x1b710b35, 0x131c471b),
u64init (0x28db77f5, 0x23047d84), u64init (0x32caab7b, 0x40c72493),
u64init (0x3c9ebe0a, 0x15c9bebc), u64init (0x431d67c4, 0x9c100d4c),
u64init (0x4cc5d4be, 0xcb3e42b6), u64init (0x597f299c, 0xfc657e2a),
u64init (0x5fcb6fab, 0x3ad6faec), u64init (0x6c44198c, 0x4a475817),
};
/* Round functions. */
#define F2(A, B, C) u64or (u64and (A, B), u64and (C, u64or (A, B)))
#define F1(E, F, G) u64xor (G, u64and (E, u64xor (F, G)))
/* Process LEN bytes of BUFFER, accumulating context into CTX.
It is assumed that LEN % 128 == 0.
Most of this code comes from GnuPG's cipher/sha1.c. */
void
sha512_process_block (const void *buffer, size_t len, struct sha512_ctx *ctx)
{
u64 const *words = (u64 const *)buffer;
u64 const *endp = words + len / sizeof (u64);
u64 x[16];
u64 a = ctx->state[0];
u64 b = ctx->state[1];
u64 c = ctx->state[2];
u64 d = ctx->state[3];
u64 e = ctx->state[4];
u64 f = ctx->state[5];
u64 g = ctx->state[6];
u64 h = ctx->state[7];
/* First increment the byte count. FIPS PUB 180-2 specifies the possible
length of the file up to 2^128 bits. Here we only compute the
number of bytes. Do a double word increment. */
ctx->total[0] = u64plus (ctx->total[0], u64lo (len));
if (u64lt (ctx->total[0], u64lo (len)))
ctx->total[1] = u64plus (ctx->total[1], u64lo (1));
#define S0(x) u64xor (u64rol(x, 63), u64xor (u64rol (x, 56), u64shr (x, 7)))
#define S1(x) u64xor (u64rol (x, 45), u64xor (u64rol (x, 3), u64shr (x, 6)))
#define SS0(x) u64xor (u64rol (x, 36), u64xor (u64rol (x, 30), u64rol (x, 25)))
#define SS1(x) u64xor (u64rol(x, 50), u64xor (u64rol (x, 46), u64rol (x, 23)))
#define M(I) (x[(I) & 15] \
= u64plus (x[(I) & 15], \
u64plus (S1 (x[((I) - 2) & 15]), \
u64plus (x[((I) - 7) & 15], \
S0 (x[((I) - 15) & 15])))))
#define R(A, B, C, D, E, F, G, H, K, M) \
do \
{ \
u64 t0 = u64plus (SS0 (A), F2 (A, B, C)); \
u64 t1 = \
u64plus (H, u64plus (SS1 (E), \
u64plus (F1 (E, F, G), u64plus (K, M)))); \
D = u64plus (D, t1); \
H = u64plus (t0, t1); \
} \
while (0)
while (words < endp)
{
int t;
/* FIXME: see sha1.c for a better implementation. */
for (t = 0; t < 16; t++)
{
x[t] = SWAP (*words);
words++;
}
R( a, b, c, d, e, f, g, h, K( 0), x[ 0] );
R( h, a, b, c, d, e, f, g, K( 1), x[ 1] );
R( g, h, a, b, c, d, e, f, K( 2), x[ 2] );
R( f, g, h, a, b, c, d, e, K( 3), x[ 3] );
R( e, f, g, h, a, b, c, d, K( 4), x[ 4] );
R( d, e, f, g, h, a, b, c, K( 5), x[ 5] );
R( c, d, e, f, g, h, a, b, K( 6), x[ 6] );
R( b, c, d, e, f, g, h, a, K( 7), x[ 7] );
R( a, b, c, d, e, f, g, h, K( 8), x[ 8] );
R( h, a, b, c, d, e, f, g, K( 9), x[ 9] );
R( g, h, a, b, c, d, e, f, K(10), x[10] );
R( f, g, h, a, b, c, d, e, K(11), x[11] );
R( e, f, g, h, a, b, c, d, K(12), x[12] );
R( d, e, f, g, h, a, b, c, K(13), x[13] );
R( c, d, e, f, g, h, a, b, K(14), x[14] );
R( b, c, d, e, f, g, h, a, K(15), x[15] );
R( a, b, c, d, e, f, g, h, K(16), M(16) );
R( h, a, b, c, d, e, f, g, K(17), M(17) );
R( g, h, a, b, c, d, e, f, K(18), M(18) );
R( f, g, h, a, b, c, d, e, K(19), M(19) );
R( e, f, g, h, a, b, c, d, K(20), M(20) );
R( d, e, f, g, h, a, b, c, K(21), M(21) );
R( c, d, e, f, g, h, a, b, K(22), M(22) );
R( b, c, d, e, f, g, h, a, K(23), M(23) );
R( a, b, c, d, e, f, g, h, K(24), M(24) );
R( h, a, b, c, d, e, f, g, K(25), M(25) );
R( g, h, a, b, c, d, e, f, K(26), M(26) );
R( f, g, h, a, b, c, d, e, K(27), M(27) );
R( e, f, g, h, a, b, c, d, K(28), M(28) );
R( d, e, f, g, h, a, b, c, K(29), M(29) );
R( c, d, e, f, g, h, a, b, K(30), M(30) );
R( b, c, d, e, f, g, h, a, K(31), M(31) );
R( a, b, c, d, e, f, g, h, K(32), M(32) );
R( h, a, b, c, d, e, f, g, K(33), M(33) );
R( g, h, a, b, c, d, e, f, K(34), M(34) );
R( f, g, h, a, b, c, d, e, K(35), M(35) );
R( e, f, g, h, a, b, c, d, K(36), M(36) );
R( d, e, f, g, h, a, b, c, K(37), M(37) );
R( c, d, e, f, g, h, a, b, K(38), M(38) );
R( b, c, d, e, f, g, h, a, K(39), M(39) );
R( a, b, c, d, e, f, g, h, K(40), M(40) );
R( h, a, b, c, d, e, f, g, K(41), M(41) );
R( g, h, a, b, c, d, e, f, K(42), M(42) );
R( f, g, h, a, b, c, d, e, K(43), M(43) );
R( e, f, g, h, a, b, c, d, K(44), M(44) );
R( d, e, f, g, h, a, b, c, K(45), M(45) );
R( c, d, e, f, g, h, a, b, K(46), M(46) );
R( b, c, d, e, f, g, h, a, K(47), M(47) );
R( a, b, c, d, e, f, g, h, K(48), M(48) );
R( h, a, b, c, d, e, f, g, K(49), M(49) );
R( g, h, a, b, c, d, e, f, K(50), M(50) );
R( f, g, h, a, b, c, d, e, K(51), M(51) );
R( e, f, g, h, a, b, c, d, K(52), M(52) );
R( d, e, f, g, h, a, b, c, K(53), M(53) );
R( c, d, e, f, g, h, a, b, K(54), M(54) );
R( b, c, d, e, f, g, h, a, K(55), M(55) );
R( a, b, c, d, e, f, g, h, K(56), M(56) );
R( h, a, b, c, d, e, f, g, K(57), M(57) );
R( g, h, a, b, c, d, e, f, K(58), M(58) );
R( f, g, h, a, b, c, d, e, K(59), M(59) );
R( e, f, g, h, a, b, c, d, K(60), M(60) );
R( d, e, f, g, h, a, b, c, K(61), M(61) );
R( c, d, e, f, g, h, a, b, K(62), M(62) );
R( b, c, d, e, f, g, h, a, K(63), M(63) );
R( a, b, c, d, e, f, g, h, K(64), M(64) );
R( h, a, b, c, d, e, f, g, K(65), M(65) );
R( g, h, a, b, c, d, e, f, K(66), M(66) );
R( f, g, h, a, b, c, d, e, K(67), M(67) );
R( e, f, g, h, a, b, c, d, K(68), M(68) );
R( d, e, f, g, h, a, b, c, K(69), M(69) );
R( c, d, e, f, g, h, a, b, K(70), M(70) );
R( b, c, d, e, f, g, h, a, K(71), M(71) );
R( a, b, c, d, e, f, g, h, K(72), M(72) );
R( h, a, b, c, d, e, f, g, K(73), M(73) );
R( g, h, a, b, c, d, e, f, K(74), M(74) );
R( f, g, h, a, b, c, d, e, K(75), M(75) );
R( e, f, g, h, a, b, c, d, K(76), M(76) );
R( d, e, f, g, h, a, b, c, K(77), M(77) );
R( c, d, e, f, g, h, a, b, K(78), M(78) );
R( b, c, d, e, f, g, h, a, K(79), M(79) );
a = ctx->state[0] = u64plus (ctx->state[0], a);
b = ctx->state[1] = u64plus (ctx->state[1], b);
c = ctx->state[2] = u64plus (ctx->state[2], c);
d = ctx->state[3] = u64plus (ctx->state[3], d);
e = ctx->state[4] = u64plus (ctx->state[4], e);
f = ctx->state[5] = u64plus (ctx->state[5], f);
g = ctx->state[6] = u64plus (ctx->state[6], g);
h = ctx->state[7] = u64plus (ctx->state[7], h);
}
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,506 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "base64.h"
#include "hmac.h"
#include "sha1.h"
#include "sha256.h"
#include "spas_client.h"
#ifdef WIN32
#include <io.h>
#include <process.h>
#else
#include <unistd.h>
#endif
#ifdef SPAS_MT
#include <pthread.h>
#endif
#ifdef __cplusplus
namespace rocketmqSignature {
#endif
#define SPAS_VERSION "SPAS_V1_0"
static SPAS_CREDENTIAL g_credential;
static char g_path[SPAS_MAX_PATH];
static int g_loaded = 0;
static unsigned int refresh = 10;
static time_t modified = 0;
#ifdef SPAS_MT
static pthread_mutex_t cred_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_once_t cred_once = PTHREAD_ONCE_INIT;
static pthread_key_t cred_key;
#endif
extern void *_mem_alloc(unsigned int size);
extern void *_mem_realloc(void *ptr, unsigned int old_size,
unsigned int new_size);
extern void _mem_free(void *ptr);
extern void _trim(char *str);
void *_mem_alloc(unsigned int size) {
void *p = malloc(size);
if (p != NULL) {
memset(p, 0, size);
}
return p;
}
void *_mem_realloc(void *ptr, unsigned int old_size, unsigned int new_size) {
void *p = realloc(ptr, new_size);
if (p != NULL && new_size > old_size) {
memset((unsigned int *)p + old_size, 0, new_size - old_size);
}
return p;
}
void _mem_free(void *ptr) { free(ptr); }
void _trim(char *str) {
int len = strlen(str);
int i;
int done = 0;
for (i = len - 1; i >= 0; i--) {
switch (str[i]) {
case ' ':
case '\t':
case '\r':
case '\n':
str[i] = '\0';
break;
default:
done = 1;
break;
}
if (done) {
break;
}
}
}
static int _load_credential(SPAS_CREDENTIAL *pcred, char *path) {
FILE *fp = NULL;
char buf[SPAS_MAX_KEY_LEN * 2];
if (pcred == NULL || path == NULL) {
return ERROR_INVALID_PARAM;
}
fp = fopen(path, "r");
if (fp == NULL) {
return ERROR_FILE_OPEN;
}
memset(pcred, 0, sizeof(SPAS_CREDENTIAL));
while (fgets(buf, sizeof(buf), fp)) {
_trim(buf);
int len = strlen(SPAS_ACCESS_KEY_TAG);
if (strncmp(buf, SPAS_ACCESS_KEY_TAG, len) == 0 && buf[len] == '=') {
strncpy(pcred->access_key, buf + len + 1, SPAS_MAX_KEY_LEN - 1);
} else {
len = strlen(SPAS_SECRET_KEY_TAG);
if (strncmp(buf, SPAS_SECRET_KEY_TAG, len) == 0 && buf[len] == '=') {
strncpy(pcred->secret_key, buf + len + 1, SPAS_MAX_KEY_LEN - 1);
}
}
}
fclose(fp);
if (strlen(pcred->access_key) == 0 || strlen(pcred->secret_key) == 0) {
return ERROR_MISSING_KEY;
}
return SPAS_NO_ERROR;
}
#ifndef WIN32
static void _reload_credential(int sig) {
int ret;
SPAS_CREDENTIAL credential;
struct stat status;
struct sigaction act;
if (sig != SIGALRM) {
return;
}
memset(&act, 0, sizeof(act));
act.sa_handler = _reload_credential;
sigaction(SIGALRM, &act, NULL);
alarm(refresh);
if (g_path[0] != '\0') {
ret = stat(g_path, &status);
if (ret != 0) {
return;
}
if (status.st_mtime == modified) {
return;
}
ret = _load_credential(&credential, g_path);
if (ret != SPAS_NO_ERROR) {
return;
}
#ifdef SPAS_MT
pthread_mutex_lock(&cred_mutex);
#endif
memcpy(&g_credential, &credential, sizeof(SPAS_CREDENTIAL));
#ifdef SPAS_MT
pthread_mutex_unlock(&cred_mutex);
#endif
modified = status.st_mtime;
}
}
static int _update_credential_by_alarm() {
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = _reload_credential;
sigaction(SIGALRM, &act, NULL);
alarm(refresh);
return SPAS_NO_ERROR;
}
#endif
#ifdef SPAS_MT
static void *_update_credential_entry(void *arg) {
int ret;
SPAS_CREDENTIAL credential;
struct stat status;
struct timeval tv;
while (1) {
tv.tv_sec = refresh;
tv.tv_usec = 0;
select(0, NULL, NULL, NULL, &tv);
if (g_path[0] != '\0') {
ret = stat(g_path, &status);
if (ret != 0) {
continue;
}
if (status.st_mtime == modified) {
continue;
}
ret = _load_credential(&credential, g_path);
if (ret != SPAS_NO_ERROR) {
continue;
}
pthread_mutex_lock(&cred_mutex);
memcpy(&g_credential, &credential, sizeof(SPAS_CREDENTIAL));
pthread_mutex_unlock(&cred_mutex);
modified = status.st_mtime;
}
}
return NULL;
}
static int _update_credential_by_thread() {
pthread_t tid;
int ret;
ret = pthread_create(&tid, NULL, _update_credential_entry, NULL);
if (ret != 0) {
return ERROR_UPDATE_CREDENTIAL;
}
pthread_detach(tid);
return SPAS_NO_ERROR;
}
int spas_load_credential(char *path, CREDENTIAL_UPDATE_MODE mode) {
int ret = SPAS_NO_ERROR;
SPAS_CREDENTIAL credential;
if (g_loaded) {
return SPAS_NO_ERROR;
}
if (path == NULL) {
path = getenv(SPAS_CREDENTIAL_ENV);
if (path == NULL) {
return ERROR_NO_CREDENTIAL;
}
}
strncpy(g_path, path, SPAS_MAX_PATH - 1);
ret = _load_credential(&credential, path);
if (ret != SPAS_NO_ERROR) {
return ret;
}
#ifdef SPAS_MT
pthread_mutex_lock(&cred_mutex);
#endif
if (!g_loaded) {
memcpy(&g_credential, &credential, sizeof(SPAS_CREDENTIAL));
g_loaded = 1;
}
#ifdef SPAS_MT
pthread_mutex_unlock(&cred_mutex);
#endif
switch (mode) {
case UPDATE_BY_ALARM:
ret = _update_credential_by_alarm();
break;
#ifdef SPAS_MT
case UPDATE_BY_THREAD:
ret = _update_credential_by_thread();
break;
#endif
case NO_UPDATE:
default:
ret = SPAS_NO_ERROR;
break;
}
return ret;
}
#endif
SPAS_CREDENTIAL *spas_get_credential(void) {
SPAS_CREDENTIAL *credential =
(SPAS_CREDENTIAL *)_mem_alloc(sizeof(SPAS_CREDENTIAL));
if (credential != NULL) {
#ifdef SPAS_MT
pthread_mutex_lock(&cred_mutex);
#endif
memcpy(credential, &g_credential, sizeof(SPAS_CREDENTIAL));
#ifdef SPAS_MT
pthread_mutex_unlock(&cred_mutex);
#endif
}
return credential;
}
int spas_set_access_key(char *key) {
int len = 0;
if (key == NULL) {
return ERROR_INVALID_PARAM;
}
len = strlen(key);
if (len == 0 || len >= SPAS_MAX_KEY_LEN) {
return ERROR_KEY_LENGTH;
}
#ifdef SPAS_MT
pthread_mutex_lock(&cred_mutex);
#endif
memcpy(g_credential.access_key, key, len + 1);
#ifdef SPAS_MT
pthread_mutex_unlock(&cred_mutex);
#endif
return SPAS_NO_ERROR;
}
int spas_set_secret_key(char *key) {
int len = 0;
if (key == NULL) {
return ERROR_INVALID_PARAM;
}
len = strlen(key);
if (len == 0 || len >= SPAS_MAX_KEY_LEN) {
return ERROR_KEY_LENGTH;
}
#ifdef SPAS_MT
pthread_mutex_lock(&cred_mutex);
#endif
memcpy(g_credential.secret_key, key, len + 1);
#ifdef SPAS_MT
pthread_mutex_unlock(&cred_mutex);
#endif
return SPAS_NO_ERROR;
}
char *spas_get_access_key() { return g_credential.access_key; }
char *spas_get_secret_key() { return g_credential.secret_key; }
#ifdef SPAS_MT
static void _free_thread_credential(void *credential) {
if (credential != NULL) {
_mem_free(credential);
}
}
static void _init_credential_key(void) {
pthread_key_create(&cred_key, _free_thread_credential);
}
static SPAS_CREDENTIAL *_get_thread_credential(void) {
int ret = 0;
SPAS_CREDENTIAL *credential = NULL;
ret = pthread_once(&cred_once, _init_credential_key);
if (ret != 0) {
return NULL;
}
credential = pthread_getspecific(cred_key);
if (credential == NULL) {
credential = _mem_alloc(sizeof(SPAS_CREDENTIAL));
if (credential == NULL) {
return NULL;
}
ret = pthread_setspecific(cred_key, credential);
if (ret != 0) {
_mem_free(credential);
return NULL;
}
}
return credential;
}
int spas_load_thread_credential(char *path) {
int ret = SPAS_NO_ERROR;
SPAS_CREDENTIAL *credential = NULL;
credential = _get_thread_credential();
if (credential == NULL) {
return ERROR_MEM_ALLOC;
}
ret = _load_credential(credential, path);
if (ret != SPAS_NO_ERROR) {
memset(credential, 0, sizeof(SPAS_CREDENTIAL));
return ret;
}
return SPAS_NO_ERROR;
}
int spas_set_thread_access_key(char *key) {
int len = 0;
SPAS_CREDENTIAL *credential = NULL;
if (key == NULL) {
return ERROR_INVALID_PARAM;
}
len = strlen(key);
if (len == 0 || len >= SPAS_MAX_KEY_LEN) {
return ERROR_KEY_LENGTH;
}
credential = _get_thread_credential();
if (credential == NULL) {
return ERROR_MEM_ALLOC;
}
memcpy(credential->access_key, key, len + 1);
return SPAS_NO_ERROR;
}
int spas_set_thread_secret_key(char *key) {
int len = 0;
SPAS_CREDENTIAL *credential = NULL;
if (key == NULL) {
return ERROR_INVALID_PARAM;
}
len = strlen(key);
if (len == 0 || len >= SPAS_MAX_KEY_LEN) {
return ERROR_KEY_LENGTH;
}
credential = _get_thread_credential();
if (credential == NULL) {
return ERROR_MEM_ALLOC;
}
memcpy(credential->secret_key, key, len + 1);
return SPAS_NO_ERROR;
}
char *spas_get_thread_access_key(void) {
SPAS_CREDENTIAL *credential = _get_thread_credential();
if (credential == NULL) {
return NULL;
}
return credential->access_key;
}
char *spas_get_thread_secret_key(void) {
SPAS_CREDENTIAL *credential = _get_thread_credential();
if (credential == NULL) {
return NULL;
}
return credential->secret_key;
}
#endif
char *spas_get_signature(const SPAS_PARAM_LIST *list, const char *key) {
return spas_get_signature2(list, key, SIGN_HMACSHA1);
}
char *spas_get_signature2(const SPAS_PARAM_LIST *list, const char *key,
SPAS_SIGN_ALGORITHM algorithm) {
char *sign = NULL;
char *data = NULL;
if (list == NULL || key == NULL) {
return NULL;
}
data = param_list_to_str(list);
if (data == NULL) {
return NULL;
}
sign = spas_sign2(data, strlen(data), key, algorithm);
_mem_free(data);
return sign;
}
char *spas_sign(const char *data, size_t size, const char *key) {
return spas_sign2(data, size, key, SIGN_HMACSHA1);
}
char *spas_sign2(const char *data, size_t size, const char *key,
SPAS_SIGN_ALGORITHM algorithm) {
int ret;
int dsize = 0;
char *sha_buf = NULL;
char *base64_ret = NULL;
if (data == NULL || key == NULL) {
return NULL;
}
if (algorithm == SIGN_HMACSHA1) {
dsize = SHA1_DIGEST_SIZE;
sha_buf = (char *)_mem_alloc(dsize + 1);
if (sha_buf == NULL) {
return NULL;
}
ret = hmac_sha1(key, strlen(key), data, size, sha_buf);
if (ret < 0) {
_mem_free(sha_buf);
return NULL;
}
} else if (algorithm == SIGN_HMACSHA256) {
dsize = SHA256_DIGEST_SIZE;
sha_buf = (char *)_mem_alloc(dsize + 1);
if (sha_buf == NULL) {
return NULL;
}
ret = hmac_sha256(key, strlen(key), data, strlen(data), sha_buf);
if (ret < 0) {
_mem_free(sha_buf);
return NULL;
}
} else {
return NULL;
}
ret = base64_encode_alloc(sha_buf, dsize, &base64_ret);
_mem_free(sha_buf);
return base64_ret;
}
void spas_mem_free(char *pSignature) { _mem_free(pSignature); }
char *spas_get_version(void) { return SPAS_VERSION; }
#ifdef __cplusplus
}
#endif