Skip to content
This repository was archived by the owner on Apr 17, 2024. It is now read-only.

Commit a5a996a

Browse files
ioannanedelcucopybara-github
authored andcommitted
Add SLH-DSA private key object.
PiperOrigin-RevId: 625306982
1 parent 131b96f commit a5a996a

File tree

3 files changed

+436
-0
lines changed

3 files changed

+436
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// Copyright 2024 Google LLC
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+
////////////////////////////////////////////////////////////////////////////////
16+
17+
#include "tink/experimental/pqcrypto/signature/slh_dsa_private_key.h"
18+
19+
#include <cstdint>
20+
#include <string>
21+
22+
#include "absl/status/status.h"
23+
#include "absl/strings/string_view.h"
24+
#include "openssl/boringssl/src/include/openssl/mem.h"
25+
#define OPENSSL_UNSTABLE_EXPERIMENTAL_SPX
26+
#include "openssl/experimental/spx.h"
27+
#undef OPENSSL_UNSTABLE_EXPERIMENTAL_SPX
28+
#include "tink/experimental/pqcrypto/signature/slh_dsa_public_key.h"
29+
#include "tink/insecure_secret_key_access.h"
30+
#include "tink/key.h"
31+
#include "tink/partial_key_access_token.h"
32+
#include "tink/restricted_data.h"
33+
#include "tink/util/status.h"
34+
#include "tink/util/statusor.h"
35+
36+
namespace crypto {
37+
namespace tink {
38+
39+
util::StatusOr<SlhDsaPrivateKey> SlhDsaPrivateKey::Create(
40+
const SlhDsaPublicKey& public_key, const RestrictedData& private_key_bytes,
41+
PartialKeyAccessToken token) {
42+
// Only 64-byte private keys are currently supported.
43+
if (private_key_bytes.size() != SPX_SECRET_KEY_BYTES) {
44+
return util::Status(absl::StatusCode::kInvalidArgument,
45+
"SLH-DSA private key length must be 64 bytes.");
46+
}
47+
48+
if (public_key.GetParameters().GetPrivateKeySizeInBytes() !=
49+
private_key_bytes.size()) {
50+
return util::Status(absl::StatusCode::kInvalidArgument,
51+
"Private key size does not match parameters");
52+
}
53+
// Confirm that the private key and public key are a valid SLH-DSA key pair.
54+
std::string public_key_bytes_regen;
55+
public_key_bytes_regen.resize(SPX_PUBLIC_KEY_BYTES);
56+
std::string private_key_bytes_regen;
57+
private_key_bytes_regen.resize(SPX_SECRET_KEY_BYTES);
58+
59+
absl::string_view expected_private_key_bytes =
60+
private_key_bytes.GetSecret(InsecureSecretKeyAccess::Get());
61+
SPX_generate_key_from_seed(
62+
reinterpret_cast<uint8_t*>(public_key_bytes_regen.data()),
63+
reinterpret_cast<uint8_t*>(private_key_bytes_regen.data()),
64+
// Uses the first 48 bytes of the private key as seed.
65+
reinterpret_cast<const uint8_t*>(expected_private_key_bytes.data()));
66+
67+
absl::string_view expected_public_key_bytes =
68+
public_key.GetPublicKeyBytes(token);
69+
70+
if (CRYPTO_memcmp(expected_public_key_bytes.data(),
71+
public_key_bytes_regen.data(), SPX_PUBLIC_KEY_BYTES) != 0 ||
72+
CRYPTO_memcmp(expected_private_key_bytes.data(),
73+
private_key_bytes_regen.data(),
74+
SPX_SECRET_KEY_BYTES) != 0) {
75+
return util::Status(absl::StatusCode::kInvalidArgument,
76+
"Invalid SLH-DSA key pair");
77+
}
78+
79+
return SlhDsaPrivateKey(public_key, private_key_bytes);
80+
}
81+
82+
bool SlhDsaPrivateKey::operator==(const Key& other) const {
83+
const SlhDsaPrivateKey* that = dynamic_cast<const SlhDsaPrivateKey*>(&other);
84+
if (that == nullptr) {
85+
return false;
86+
}
87+
return public_key_ == that->public_key_ &&
88+
private_key_bytes_ == that->private_key_bytes_;
89+
}
90+
91+
} // namespace tink
92+
} // namespace crypto
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// Copyright 2024 Google LLC
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+
////////////////////////////////////////////////////////////////////////////////
16+
17+
#ifndef TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SLH_DSA_PRIVATE_KEY_H_
18+
#define TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SLH_DSA_PRIVATE_KEY_H_
19+
20+
#include "tink/key.h"
21+
#include "tink/partial_key_access_token.h"
22+
#include "tink/restricted_data.h"
23+
#include "tink/experimental/pqcrypto/signature/slh_dsa_public_key.h"
24+
#include "tink/signature/signature_private_key.h"
25+
#include "tink/util/statusor.h"
26+
27+
namespace crypto {
28+
namespace tink {
29+
30+
class SlhDsaPrivateKey : public SignaturePrivateKey {
31+
public:
32+
// Copyable and movable.
33+
SlhDsaPrivateKey(const SlhDsaPrivateKey& other) = default;
34+
SlhDsaPrivateKey& operator=(const SlhDsaPrivateKey& other) = default;
35+
SlhDsaPrivateKey(SlhDsaPrivateKey&& other) = default;
36+
SlhDsaPrivateKey& operator=(SlhDsaPrivateKey&& other) = default;
37+
38+
// Creates a new SLH-DSA private key from `private_key_bytes`. Returns an
39+
// error if `public_key` does not belong to the same key pair as
40+
// `private_key_bytes`.
41+
static util::StatusOr<SlhDsaPrivateKey> Create(
42+
const SlhDsaPublicKey& public_key,
43+
const RestrictedData& private_key_bytes, PartialKeyAccessToken token);
44+
45+
const RestrictedData& GetPrivateKeyBytes(PartialKeyAccessToken token) const {
46+
return private_key_bytes_;
47+
}
48+
49+
const SlhDsaPublicKey& GetPublicKey() const override { return public_key_; }
50+
51+
bool operator==(const Key& other) const override;
52+
53+
private:
54+
explicit SlhDsaPrivateKey(const SlhDsaPublicKey& public_key,
55+
const RestrictedData& private_key_bytes)
56+
: public_key_(public_key), private_key_bytes_(private_key_bytes) {}
57+
58+
SlhDsaPublicKey public_key_;
59+
RestrictedData private_key_bytes_;
60+
};
61+
62+
} // namespace tink
63+
} // namespace crypto
64+
65+
#endif // TINK_EXPERIMENTAL_PQCRYPTO_SIGNATURE_SLH_DSA_PRIVATE_KEY_H_

0 commit comments

Comments
 (0)