<p>This would probably be more suitable asked on <a href="https://crypto.stackexchange.com/">Cryptography StackExchange</a>.</p>
<p>I <em>think</em> that <code>SHA256()</code> is preferred over the <code>_CTX, _Init, _Update, _Final</code> functions. IIRC, these latter &quot;low-level&quot; functions are deprecated for external usage:</p>
<blockquote>
<p>SHA256 low level APIs are deprecated for public use, but still ok for internal use. <a href="https://github.com/openssl/openssl/blob/43ba1573ce54777b77c1990973b50731062d45b7/crypto/sha/sha256.c#L11" rel="nofollow noreferrer">Source 1</a>, <a href="https://github.com/openssl/openssl/blob/43ba1573ce54777b77c1990973b50731062d45b7/include/openssl/sha.h#L73-L78" rel="nofollow noreferrer">Source 2</a>.</p>
</blockquote>
<p>The recommended method is to use the EVP interface, which is what <code>SHA256()</code> does.</p>
<p>Based on <a href="https://github.com/openssl/openssl/blob/43ba1573ce54777b77c1990973b50731062d45b7/crypto/sha/sha1_one.c#L62" rel="nofollow noreferrer">this code here</a>, the return value is either the third parameter, or a null pointer.</p>

CC BY-SA 4.0
2021-12-31T08:15:20.283Z
Note the implementation using `EVP_Q_digest` is new in 3.0.x, which many systems and people aren't yet using; [in 1.1.1](https://github.com/openssl/openssl/blob/OpenSSL_1_1_1-stable/crypto/sha/sha256.c#L63) and below it used the lowlevel Init,Update,Final, which were not deprecated.
dave_thompson_085
CC BY-SA 4.0
2022-10-27T13:05:07.683Z
@dave_thompson_085 on the other hand older OpenSSL versions won't spit deprecation warnings when using `SHA256_Init()`, `SHA256_Update()` and `SHA256_Final()`. The older OpenSSL versions obviously [used those instead](https://github.com/openssl/openssl/blob/a598ed0dc444e010973c51e024e9b497a9340fee/crypto/sha/sha256.c#L63).
0xC0000022L
CC BY-SA 4.0
2022-10-27T15:50:41.067Z
@0xC0000022L that's exactly what he said.
meshcollider
CC BY-SA 4.0
2022-10-27T17:09:37.803Z
@meshcollider it wasn't _exactly_ but definitely very close to what he said. Which is why I upvoted the comment and tried to add some _more_ context. Apologies if that offended you.
0xC0000022L
CC BY-SA 4.0
2021-12-30T02:20:21.003Z
2021-12-30T07:48:24.423Z
2021-12-30T07:48:24.423Z
meshcollider
<blockquote>
<p>Is there any reason to do this...</p>
<pre><code>SHA256_CTX sha256;
SHA256_Init (&amp;sha256);
SHA256_Update (&amp;sha256, text, len);
SHA256_Final (hash, &amp;sha256);
</code></pre>
</blockquote>
<p>Yes there is. But not for your particular case.</p>
<p>The reason would be if you <em>do not</em> have a contiguous buffer to which you can point the &quot;composite&quot; <code>SHA256()</code> function.</p>
<p>As it so happens there are quite a few scenarios where you can run into this. The most common is probably that you are trying not to be wasteful with memory. Another is that you have a multi-GiB file; then - depending on the constraints placed on your own implementation - you may not be able to even allocate a contiguous buffer large enough to accommodate the full size of the file. Now if you wanted to compute the digest (here SHA2) hash on that, it could be better to do something like this instead (pseudo code):</p>
<pre><code>SHA256_CTX sha256;
SHA256_Init(&amp;sha256);
FILE* f = ...; // pretend it's valid and gets cleaned up
while(true)
{
    unsigned char buf[4096];
    // in case we get less bytes back than we request
    size_t actual_len = read_from_file(f, buf, sizeof(buf));
    SHA256_Update(&amp;sha256, buf, actual_len);
}
SHA256_Final(hash, &amp;sha256);
</code></pre>
<p>And <strong>that's</strong> the reason why it is so annoying that those three functions are now deprecated. Sure, EVP offers replacements, but their semantics differ quite a bit. In particular you can no longer keep the context in a stack variable unless you have some sort of smart pointer.</p>
<blockquote>
<p>For me, they both produce the same result. Are there situations where they might not?</p>
</blockquote>
<p>Not really. For cases where it is practical to pass a contiguous buffer and a length, these are equivalent as you pointed out in your question.</p>

CC BY-SA 4.0
2022-10-27T13:01:28.307Z
2022-10-27T13:01:28.307Z
0xC0000022L
<p>Given the following variables:</p>
<pre><code>unsigned char text [] = &quot;Test String&quot;;
unsigned int len = strlen ((const char*) text);
unsigned char hash [SHA256_DIGEST_LENGTH];
</code></pre>
<p>Is there any reason to do this...</p>
<pre><code>SHA256_CTX sha256;
SHA256_Init (&amp;sha256);
SHA256_Update (&amp;sha256, text, len);
SHA256_Final (hash, &amp;sha256);
</code></pre>
<p>instead of simply doing this?</p>
<pre><code>SHA256 (text, len, hash);
</code></pre>
<p>For me, they both produce the same result. Are there situations where they might not?</p>
<p>Also, does the SHA256 function always return the same pointer that was passed as its third parameter, or are there cases where it might return something else?</p>

<sha256><c++><openssl>
Proper way to get sha256 hash in c++ using openssl?
Zephyrus
# Proper way to get sha256 hash in c++ using openssl?

(Asked by: username_0 on 2021-12-29)

Given the following variables:
unsigned char text [] = "Test String";
unsigned int len = strlen ((const char*) text);
unsigned char hash [SHA256_DIGEST_LENGTH];

Is there any reason to do this...
SHA256_CTX sha256;
SHA256_Init (&sha256);
SHA256_Update (&sha256, text, len);
SHA256_Final (hash, &sha256);

instead of simply doing this?
SHA256 (text, len, hash);

For me, they both produce the same result. Are there situations where they might not?
Also, does the SHA256 function always return the same pointer that was passed as its third parameter, or are there cases where it might return something else?

**Tags:** sha256, c++, openssl


---

## 2 answers

### Answer by username_1 on 2021-12-30. Score: 1 | Accepted answer

This would probably be more suitable asked on [Cryptography StackExchange](https://crypto.stackexchange.com/).

I *think* that `SHA256()` is preferred over the `_CTX, _Init, _Update, _Final` functions. IIRC, these latter "low-level" functions are deprecated for external usage:

> SHA256 low level APIs are deprecated for public use, but still ok for internal use. [Source 1](https://github.com/openssl/openssl/blob/43ba1573ce54777b77c1990973b50731062d45b7/crypto/sha/sha256.c#L11), [Source 2](https://github.com/openssl/openssl/blob/43ba1573ce54777b77c1990973b50731062d45b7/include/openssl/sha.h#L73-L78).

The recommended method is to use the EVP interface, which is what `SHA256()` does.

Based on [this code here](https://github.com/openssl/openssl/blob/43ba1573ce54777b77c1990973b50731062d45b7/crypto/sha/sha1_one.c#L62), the return value is either the third parameter, or a null pointer.

> **Comments:**
> **username_2**: Note the implementation using `EVP_Q_digest` is new in 3.0.x, which many systems and people aren't yet using; [in 1.1.1](https://github.com/openssl/openssl/blob/OpenSSL_1_1_1-stable/crypto/sha/sha256.c#L63) and below it used the lowlevel Init,Update,Final, which were not deprecated.  
> **username_3**: @username_2 on the other hand older OpenSSL versions won't spit deprecation warnings when using `SHA256_Init()`, `SHA256_Update()` and `SHA256_Final()`. The older OpenSSL versions obviously [used those instead](https://github.com/openssl/openssl/blob/a598ed0dc444e010973c51e024e9b497a9340fee/crypto/sha/sha256.c#L63).  
> **username_1**: @username_3 that's exactly what he said.  
> **username_3**: @username_1 it wasn't _exactly_ but definitely very close to what he said. Which is why I upvoted the comment and tried to add some _more_ context. Apologies if that offended you.  

---

### Answer by username_3 on 2022-10-27. Score: 1

Is there any reason to do this...
SHA256_CTX sha256;
SHA256_Init (&sha256);
SHA256_Update (&sha256, text, len);
SHA256_Final (hash, &sha256);


Yes there is. But not for your particular case.
The reason would be if you do not have a contiguous buffer to which you can point the "composite" SHA256() function.
As it so happens there are quite a few scenarios where you can run into this. The most common is probably that you are trying not to be wasteful with memory. Another is that you have a multi-GiB file; then - depending on the constraints placed on your own implementation - you may not be able to even allocate a contiguous buffer large enough to accommodate the full size of the file. Now if you wanted to compute the digest (here SHA2) hash on that, it could be better to do something like this instead (pseudo code):
SHA256_CTX sha256;
SHA256_Init(&sha256);
FILE* f = ...; // pretend it's valid and gets cleaned up
while(true)
{
    unsigned char buf[4096];
    // in case we get less bytes back than we request
    size_t actual_len = read_from_file(f, buf, sizeof(buf));
    SHA256_Update(&sha256, buf, actual_len);
}
SHA256_Final(hash, &sha256);

And that's the reason why it is so annoying that those three functions are now deprecated. Sure, EVP offers replacements, but their semantics differ quite a bit. In particular you can no longer keep the context in a stack variable unless you have some sort of smart pointer.

For me, they both produce the same result. Are there situations where they might not?

Not really. For cases where it is practical to pass a contiguous buffer and a length, these are equivalent as you pointed out in your question.


---

