使用OS提供的API在MacOS上放置

Hashing on MacOS using API provided by OS

本文关键字:MacOS API OS 使用      更新时间:2023-10-16

对于我们的C/C 应用,我们使用的是Security Transforms API进行一些基本的加密/解密。
现在,我们需要计算数据的哈希(尤其是SHA256(,尽管文档声称安全性转换也提供了一种哈希的方式,但似乎没有关于如何执行的详细信息。似乎Google也没有任何示例或细节。
所以问题是:
是否真的有可能使用安全转换计算哈希(SHA256(?
如果没有,那么是否还有其他API(由Apple提供(可以使用C/C ?

对其进行计算。

我不知道安全变换。不过,您可以使用Apple的CommonCrypto库。

奇怪的是,许多commoncrypto似乎并没有得到充分记录(至少我能找到(,而是在https://opensource.apple.com//source/commoncrypto/commoncrypto/commoncrypto-7/commoncrypto-7/commoncrypto-7/commoncrypto/commoncrypto/commondigest.h一下。auto.html查找以下声明:

extern int CC_SHA256_Init(CC_SHA256_CTX *c);
extern int CC_SHA256_Update(CC_SHA256_CTX *c, const void *data, CC_LONG len);
extern int CC_SHA256_Final(unsigned char *md, CC_SHA256_CTX *c);

挖掘很多东西后,事实证明,它是可能的,但使用安全性转换API,尽管未记录下来。为了使其正常工作,用secdigesttransformcreate和使用的可用哈希算法的列表制成了AES加密的样品。

这是C 友好解决方案:

#include <CoreFoundation/CoreFoundation.h>
#include <Security/Security.h>
#ifdef __cplusplus
#include <vector>
#else // C
#include <stdbool.h> // For adding boolean support
#endif // __cplusplus
// Convenience define for cleanup
#define _CLEANUP_IF(a) if ((a)) goto Cleanup;
#ifdef __cplusplus
// Wrap into class in case of C++
class Sha256Calculator {
public:
#endif // __cplusplus
    // Calculates SHA256 hash from given array of data and returns array
    // Note: Parameter "outHash" is manually allocated so consider calling free(outHash) after using it
    static bool calculateSha256(uint8_t** outHash, size_t* outHashSize, const uint8_t *data, const size_t dataSize)
    {
        bool result = false;
        CFErrorRef error = NULL;
        SecTransformRef digestTransform = NULL;
        CFDataRef sourceData = NULL;
        CFDataRef outDataRef = NULL;
        const UInt8 * outData = NULL;
        CFIndex outDataSize = 0;

        // Create a CFData object from the source
        sourceData = CFDataCreate(kCFAllocatorDefault, (const UInt8*)data, dataSize);
        _CLEANUP_IF(!sourceData);
        digestTransform = SecDigestTransformCreate(kSecDigestSHA2, 256, &error);
        _CLEANUP_IF(error);
        SecTransformSetAttribute(digestTransform, kSecTransformInputAttributeName, (CFDataRef)sourceData, &error);
        _CLEANUP_IF(error);
        outDataRef = (CFDataRef)SecTransformExecute(digestTransform, &error);
        _CLEANUP_IF(error);
        _CLEANUP_IF(!outDataRef);

        // Extract data from CFDataRef to array
        outData = CFDataGetBytePtr(outDataRef);     // Returns read-only (UInt8*) pointer to the data
        outDataSize = CFDataGetLength(outDataRef);

        if (outHash) {
            *outHash = (uint8_t*)malloc(outDataSize);
            if (*outHash) {
                memcpy(*outHash, outData, outDataSize);
                if (outHashSize) {
                    *outHashSize = (size_t)outDataSize;
                }
                result = true;
            }
        }
        // Notes:
        //   * All the objects are released except "outData" since it's handled and cleaned by using outDataRef
        //   * CFRelease throws error if the passed object is NULL, so check objects before releasing
    Cleanup:
        // Use CFShow(error) for getting details about error
        if (error) { CFRelease(error); }
        if (digestTransform) { CFRelease(digestTransform); }
        if (sourceData) { CFRelease(sourceData); }
        if (outDataRef) { CFRelease(outDataRef); }
        return result;
    }
#ifdef __cplusplus
    // Convenience method for cpp using vectors
    static bool calculateSha256(std::vector<uint8_t>& outHash, const std::vector<uint8_t>& data)
    {
        // Call original method
        uint8_t * outHashArray = nullptr;
        size_t outHashSize;
        bool result;
        result = calculateSha256(&outHashArray, &outHashSize, data.data(), data.size());
        if (!result)
            return false;
        // Put resulting array in vector
        outHash.clear();
        outHash.insert(outHash.end(), &outHashArray[0], &outHashArray[outHashSize]);
        // Clean allocated array
        if (outHashArray)
            free(outHashArray);
        return result;
    }
};
#endif // __cplusplus

注意:
为了使用>任何其他 Hashing AlgorithGM而不是SHA256可以随意修改行:
SecDigestTransformCreate(kSecDigestSHA2, 256, &error);
带有所需的哈希算法名称和适当的长度。

ps希望,苹果公司将会更新他们的文档...