1+ // Copyright 2025 Ant Group Co., Ltd.
2+ //
3+ // Licensed under the Apache License, Version 2.0 (the "License");
4+ // you may not use this file except in compliance with the License.
5+ // You may obtain a copy of the License at
6+ //
7+ // http://www.apache.org/licenses/LICENSE-2.0
8+ //
9+ // Unless required by applicable law or agreed to in writing, software
10+ // distributed under the License is distributed on an "AS IS" BASIS,
11+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+ // See the License for the specific language governing permissions and
13+ // limitations under the License.
14+
15+ #include " yacl/crypto/hash/ssl_hash_xof.h"
16+
17+ #include < openssl/evp.h>
18+
19+ #include " yacl/base/exception.h"
20+
21+ namespace yacl ::crypto {
22+
23+ SslHashXof::SslHashXof (HashAlgorithm hash_algo)
24+ : hash_algo_(hash_algo),
25+ md_ (openssl::FetchEvpMd(ToString(hash_algo))),
26+ context_(EVP_MD_CTX_new()) {
27+ YACL_ENFORCE (context_ != nullptr , " Failed to create EVP_MD_CTX" );
28+ YACL_ENFORCE (EVP_DigestInit_ex (context_.get (), md_.get (), nullptr ) == 1 ,
29+ " Failed to initialize XOF hash" );
30+ switch (hash_algo) {
31+ case HashAlgorithm::SHAKE128:
32+ digest_size_ = 32 ;
33+ break ;
34+ case HashAlgorithm::SHAKE256:
35+ digest_size_ = 64 ;
36+ break ;
37+ default :
38+ YACL_THROW (" Unsupported XOF algorithm: {}" , static_cast <int >(hash_algo));
39+ }
40+ }
41+
42+ HashInterface& SslHashXof::Reset () {
43+ OSSL_RET_1 (EVP_DigestInit_ex (context_.get (), md_.get (), nullptr ));
44+ return *this ;
45+ }
46+
47+ HashInterface& SslHashXof::Update (ByteContainerView data) {
48+ OSSL_RET_1 (EVP_DigestUpdate (context_.get (), data.data (), data.size ()));
49+ return *this ;
50+ }
51+
52+ std::vector<uint8_t > SslHashXof::CumulativeHash () const {
53+ return CumulativeHash (digest_size_);
54+ }
55+
56+ std::vector<uint8_t > SslHashXof::CumulativeHash (size_t output_length) const {
57+ std::vector<uint8_t > output (output_length);
58+ auto ctx_snapshot = openssl::UniqueMdCtx (EVP_MD_CTX_new ());
59+ YACL_ENFORCE (ctx_snapshot != nullptr );
60+
61+ EVP_MD_CTX_init (ctx_snapshot.get ());
62+ OSSL_RET_1 (EVP_MD_CTX_copy_ex (ctx_snapshot.get (), context_.get ()));
63+ OSSL_RET_1 (
64+ EVP_DigestFinalXOF (ctx_snapshot.get (), output.data (), output_length));
65+
66+ return output;
67+ }
68+
69+ } // namespace yacl::crypto
0 commit comments