【问题标题】:Hashing on MacOS using API provided by OS使用 OS 提供的 API 在 MacOS 上进行散列
【发布时间】:2018-07-31 17:36:35
【问题描述】:

对于我们的 C/C++ 应用程序,我们使用 Security Transforms API 进行一些基本的加密/解密。
现在我们需要计算数据的哈希值(尤其是 SHA256),尽管文档声称 Security Transforms 也提供了一种哈希方法,但似乎没有详细说明如何做到这一点。似乎谷歌也没有提供任何例子或细节。
所以问题是:
是否真的可以使用安全转换计算哈希(如果可能,SHA256)?
如果没有,那么是否有任何其他 API(由 Apple 提供)使用 C/C++ 进行计算?

【问题讨论】:

  • 投反对票的人,能否请您澄清投反对票的原因,以便于改进问题?
  • @jww 感谢您的注意,但这是一个稍微不同的问题,因为它是关于使用目标 c,但这里我们需要 c++ 的解决方案,如果可能的话,还需要使用安全转换

标签: c++ macos hash cryptography objective-c++


【解决方案1】:

我不了解安全转换。不过,您可以使用 Apple 的 CommonCrypto 库。

奇怪的是,CommonCrypto 的大部分内容似乎都没有很好的记录(至少我可以找到),但在 https://opensource.apple.com//source/CommonCrypto/CommonCrypto-7/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);

【讨论】:

    【解决方案2】:

    经过大量挖掘后发现,Security Transforms API可能的,尽管没有记录。为了使其工作,使用SecDigestTransformCreate 制作了AES encryption 的样本,并使用了可用哈希算法列表there

    这是一个 C 和 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
    

    注意:
    为了使用任何其他散列算法代替 SHA256,请随意修改以下行:
    SecDigestTransformCreate(kSecDigestSHA2, 256, &amp;error);
    具有所需的可用哈希算法name 和适当的长度。

    PS 希望苹果会更新他们的文档...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-21
      • 1970-01-01
      • 1970-01-01
      • 2018-03-13
      相关资源
      最近更新 更多