├── .circleci
└── config.yml
├── .gitignore
├── CHANGELOG.md
├── CLA.md
├── CODE-OF-CONDUCT.md
├── CODING-CONVENTIONS.md
├── CONTRIBUTING.md
├── GOVERNANCE.md
├── LICENSE
├── README.md
├── acceptance-tests
├── build.gradle
└── src
│ ├── test
│ ├── java
│ │ └── tech
│ │ │ └── pegasys
│ │ │ └── signers
│ │ │ ├── keystorage
│ │ │ └── hashicorp
│ │ │ │ └── tests
│ │ │ │ └── HashicorpVaultAccessAcceptanceTest.java
│ │ │ └── secp256k1
│ │ │ └── tests
│ │ │ └── multikey
│ │ │ ├── AzureBasedTomlLoadingAcceptanceTest.java
│ │ │ ├── FileBasedTomlLoadingAcceptanceTest.java
│ │ │ ├── HashicorpBasedTomlLoadingAcceptanceTest.java
│ │ │ ├── HashicorpHelpers.java
│ │ │ ├── HashicorpTlsBasedTomlLoadingAcceptanceTest.java
│ │ │ ├── MultiKeyAcceptanceTestBase.java
│ │ │ └── signing
│ │ │ ├── MultiKeyAzureTransactionSignerAcceptanceTest.java
│ │ │ ├── MultiKeyFileBasedTransactionSignerAcceptanceTest.java
│ │ │ ├── MultiKeyHashicorpTransactionSignerAcceptanceTest.java
│ │ │ └── MultiKeyTransactionSigningAcceptanceTestBase.java
│ └── resources
│ │ ├── log4j2.xml
│ │ └── secp256k1
│ │ ├── UTC--2019-12-05T05-17-11.151993000Z--a01f618424b0113a9cebdc6cb66ca5b48e9120c5.key
│ │ ├── UTC--2019-12-05T05-17-11.151993000Z--a01f618424b0113a9cebdc6cb66ca5b48e9120c5.password
│ │ └── rich_benefactor_one.json
│ └── testFixtures
│ └── java
│ └── tech.pegasys.signers.secp256k1
│ ├── AllTomlConfigFilesSelector.java
│ ├── HashicorpSigningParams.java
│ ├── MultiKeyTomlFileUtil.java
│ └── SignerIdentifierConfigFileSelector.java
├── bls-keystore
├── build.gradle
└── src
│ ├── main
│ └── java
│ │ └── tech
│ │ └── pegasys
│ │ └── signers
│ │ └── bls
│ │ └── keystore
│ │ ├── KeyStore.java
│ │ ├── KeyStoreBytesModule.java
│ │ ├── KeyStoreLoader.java
│ │ ├── KeyStoreValidationException.java
│ │ ├── PasswordUtils.java
│ │ └── model
│ │ ├── Checksum.java
│ │ ├── ChecksumFunction.java
│ │ ├── Cipher.java
│ │ ├── CipherFunction.java
│ │ ├── CipherParam.java
│ │ ├── Crypto.java
│ │ ├── EmptyParam.java
│ │ ├── Kdf.java
│ │ ├── KdfFunction.java
│ │ ├── KdfParam.java
│ │ ├── KeyStoreData.java
│ │ ├── Pbkdf2Param.java
│ │ ├── Pbkdf2PseudoRandomFunction.java
│ │ └── SCryptParam.java
│ └── test
│ ├── java
│ └── tech
│ │ └── pegasys
│ │ └── signers
│ │ └── bls
│ │ └── keystore
│ │ ├── DecryptionKeyTest.java
│ │ ├── KeyStoreTest.java
│ │ ├── PasswordUtilsTest.java
│ │ └── model
│ │ └── CipherTest.java
│ └── resources
│ ├── missingKdfSectionTestVector.json
│ ├── pbkdf2TestVector.json
│ ├── scryptExtraFieldTestVector.json
│ ├── scryptTestVector.json
│ ├── scryptTestVectorWithMissingPathAndUUID.json
│ ├── unsupportedChecksumFunction.json
│ ├── unsupportedCipherFunction.json
│ ├── unsupportedDkLen.json
│ ├── unsupportedKdfFunction.json
│ ├── unsupportedPBKDF2Prf.json
│ └── v3TestVector.json
├── build.gradle
├── gradle.properties
├── gradle
├── eclipse-java-google-style.xml
├── formatter.properties
├── license-report-config
│ ├── allowed-licenses.json
│ └── license-normalizer.json
├── owasp-suppression.xml
├── spotless.bash.license
├── spotless.java.license
├── versions.gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── keystorage
├── aws
│ ├── build.gradle
│ └── src
│ │ ├── main
│ │ └── java
│ │ │ └── tech
│ │ │ └── pegasys
│ │ │ └── signers
│ │ │ └── aws
│ │ │ ├── AwsKeyIdentifier.java
│ │ │ ├── AwsSecretsManager.java
│ │ │ └── AwsSecretsManagerProvider.java
│ │ └── test
│ │ └── java
│ │ └── tech
│ │ └── pegasys
│ │ └── signers
│ │ └── aws
│ │ ├── AwsSecret.java
│ │ ├── AwsSecretsManagerProviderTest.java
│ │ ├── AwsSecretsManagerTest.java
│ │ └── SecretsMaps.java
├── azure
│ ├── build.gradle
│ └── src
│ │ ├── main
│ │ └── java
│ │ │ └── tech
│ │ │ └── pegasys
│ │ │ └── signers
│ │ │ └── azure
│ │ │ └── AzureKeyVault.java
│ │ └── test
│ │ └── java
│ │ └── tech
│ │ └── pegasys
│ │ └── signers
│ │ └── azure
│ │ └── AzureKeyVaultTest.java
├── build.gradle
├── common
│ ├── build.gradle
│ └── src
│ │ ├── main
│ │ └── java
│ │ │ └── tech
│ │ │ └── pegasys
│ │ │ └── signers
│ │ │ └── common
│ │ │ ├── MappedResults.java
│ │ │ └── SecretValueMapperUtil.java
│ │ └── test
│ │ └── java
│ │ └── tech
│ │ └── pegasys
│ │ └── signers
│ │ └── common
│ │ └── SecretValueMapperUtilTest.java
├── hashicorp
│ ├── build.gradle
│ └── src
│ │ ├── integrationTest
│ │ └── java
│ │ │ └── tech
│ │ │ └── pegasys
│ │ │ └── signers
│ │ │ └── hashicorp
│ │ │ └── HashicorpIntegrationTest.java
│ │ ├── main
│ │ └── java
│ │ │ └── tech
│ │ │ └── pegasys
│ │ │ └── signers
│ │ │ └── hashicorp
│ │ │ ├── HashicorpConnection.java
│ │ │ ├── HashicorpConnectionFactory.java
│ │ │ ├── HashicorpException.java
│ │ │ ├── HashicorpKVResponseMapper.java
│ │ │ ├── TrustManagerFactoryProvider.java
│ │ │ ├── TrustStoreType.java
│ │ │ └── config
│ │ │ ├── ConnectionParameters.java
│ │ │ ├── HashicorpKeyConfig.java
│ │ │ ├── KeyDefinition.java
│ │ │ ├── TlsOptions.java
│ │ │ └── loader
│ │ │ └── toml
│ │ │ ├── TomlConfigLoader.java
│ │ │ └── TomlParser.java
│ │ ├── test
│ │ ├── java
│ │ │ └── tech
│ │ │ │ └── pegasys
│ │ │ │ └── signers
│ │ │ │ └── hashicorp
│ │ │ │ ├── HashicorpConnectionFactoryTest.java
│ │ │ │ ├── HashicorpConnectionTest.java
│ │ │ │ ├── HashicorpKVResponseMapperTest.java
│ │ │ │ ├── TrustStoreTypeTest.java
│ │ │ │ └── loader
│ │ │ │ └── TomlConfigLoaderTest.java
│ │ └── resources
│ │ │ └── tls
│ │ │ └── cert1.pfx
│ │ └── testFixtures
│ │ └── java
│ │ └── tech
│ │ └── pegasys
│ │ └── signers
│ │ └── hashicorp
│ │ ├── dsl
│ │ ├── HashicorpNode.java
│ │ ├── HashicorpVaultCommands.java
│ │ ├── HashicorpVaultTokens.java
│ │ └── certificates
│ │ │ ├── CertificateHelpers.java
│ │ │ └── SelfSignedCertificate.java
│ │ └── util
│ │ └── HashicorpConfigUtil.java
├── interlock
│ ├── build.gradle
│ └── src
│ │ ├── main
│ │ └── java
│ │ │ └── tech
│ │ │ └── pegasys
│ │ │ └── signers
│ │ │ └── interlock
│ │ │ ├── InterlockClientException.java
│ │ │ ├── InterlockSession.java
│ │ │ ├── InterlockSessionFactory.java
│ │ │ ├── InterlockSessionFactoryProvider.java
│ │ │ ├── model
│ │ │ └── ApiAuth.java
│ │ │ └── vertx
│ │ │ ├── InterlockSessionFactoryImpl.java
│ │ │ ├── InterlockSessionImpl.java
│ │ │ └── operations
│ │ │ ├── AbstractOperation.java
│ │ │ ├── ApiOperation.java
│ │ │ ├── FileDownloadIdOperation.java
│ │ │ ├── FileDownloadOperation.java
│ │ │ ├── LoginOperation.java
│ │ │ └── LogoutOperation.java
│ │ └── test
│ │ ├── java
│ │ └── tech
│ │ │ └── pegasys
│ │ │ └── signers
│ │ │ └── interlock
│ │ │ └── InterlockClientTest.java
│ │ └── resources
│ │ └── log4j2-test.xml
└── yubihsm2
│ ├── build.gradle
│ └── src
│ ├── main
│ └── java
│ │ └── tech
│ │ └── pegasys
│ │ └── signers
│ │ └── yubihsm
│ │ ├── YubiHsm.java
│ │ ├── YubiHsmException.java
│ │ └── pkcs11
│ │ ├── ExtendedData.java
│ │ ├── Pkcs11Module.java
│ │ ├── Pkcs11Session.java
│ │ ├── Pkcs11YubiHsm.java
│ │ └── Pkcs11YubiHsmPin.java
│ └── test
│ ├── java
│ └── tech
│ │ └── pegasys
│ │ └── signers
│ │ └── yubihsm
│ │ └── ManualYubiHsmPKCS11Test.java
│ └── resources
│ └── log4j2-test.xml
├── settings.gradle
└── signing
├── build.gradle
└── secp256k1
├── api
├── build.gradle
└── src
│ └── main
│ └── java
│ └── tech
│ └── pegasys
│ └── signers
│ └── secp256k1
│ └── api
│ ├── FileSelector.java
│ ├── Signature.java
│ ├── Signer.java
│ ├── SignerIdentifier.java
│ ├── SignerProvider.java
│ ├── SingleSignerProvider.java
│ └── util
│ └── AddressUtil.java
├── build.gradle
└── impl
├── build.gradle
└── src
├── main
└── java
│ └── tech
│ └── pegasys
│ └── signers
│ └── secp256k1
│ ├── EthPublicKeyUtils.java
│ ├── azure
│ ├── AzureConfig.java
│ ├── AzureKeyVaultSigner.java
│ └── AzureKeyVaultSignerFactory.java
│ ├── common
│ ├── PasswordFileUtil.java
│ └── SignerInitializationException.java
│ ├── filebased
│ ├── CredentialSigner.java
│ ├── FileBasedSignerFactory.java
│ └── FileSignerConfig.java
│ ├── hashicorp
│ └── HashicorpSignerFactory.java
│ └── multikey
│ ├── MultiKeySignerProvider.java
│ ├── MultiSignerFactory.java
│ ├── SignerType.java
│ ├── SigningMetadataTomlConfigLoader.java
│ ├── TomlConfigFileParser.java
│ ├── TomlTableAdapter.java
│ └── metadata
│ ├── AzureSigningMetadataFile.java
│ ├── FileBasedSigningMetadataFile.java
│ ├── HashicorpSigningMetadataFile.java
│ ├── RawSigningMetadataFile.java
│ └── SigningMetadataFile.java
├── test
├── java
│ └── tech
│ │ └── pegasys
│ │ └── signers
│ │ └── secp256k1
│ │ ├── EthPublicKeyUtilsTest.java
│ │ ├── azure
│ │ └── AzureKeyVaultSignerTest.java
│ │ ├── common
│ │ └── PasswordFileUtilTest.java
│ │ ├── filebased
│ │ ├── CredentialSignerTest.java
│ │ └── FileBasedSignerTest.java
│ │ └── multikey
│ │ ├── FileBasedSigningMetadataFileTest.java
│ │ ├── HashicorpSigningMetadataTomlConfigLoaderTest.java
│ │ ├── MetadataFileFixture.java
│ │ ├── MultiKeySignerProviderTest.java
│ │ └── SigningMetadataTomlConfigLoaderTest.java
└── resources
│ └── metadata-toml-configs
│ ├── 627306090abab3a6e1400e9345bc60c78a8bef57.toml
│ ├── UTC--2019-10-23T04-00-04.860366000Z--f17f52151ebef6c7334fad080c5704d77216b732.toml
│ ├── azureconfig.toml
│ ├── azureconfig_illegalValueType.toml
│ ├── azureconfig_missingField.toml
│ ├── bar_fe3b557e8fb62b89f4916b721be55ceb828dbd73.toml
│ ├── duplicate_bar_627306090abab3a6e1400e9345bc60c78a8bef61.toml
│ ├── duplicate_foo_627306090abab3a6e1400e9345bc60c78a8bef61.toml
│ ├── k.key
│ ├── key_password_relative_path.toml
│ ├── missing_key_and_password_file_fe3b557e8fb62b89f4916b721be55ceb828dbd78.toml
│ ├── missing_key_file_fe3b557e8fb62b89f4916b721be55ceb828dbd76.toml
│ ├── missing_password_file_fe3b557e8fb62b89f4916b721be55ceb828dbd77.toml
│ ├── p.password
│ └── unknown_type_signer_fe3b557e8fb62b89f4916b721be55ceb828dbd75.toml
└── testFixtures
└── java
└── tech
└── pegasys
└── signers
└── secp256k1
└── common
├── PublicKeySignerIdentifier.java
└── TomlStringBuilder.java
/.gitignore:
--------------------------------------------------------------------------------
1 | *.bak
2 | *.swp
3 | *.tmp
4 | *~.nib
5 | *.iml
6 | *.launch
7 | *.swp
8 | *.log
9 | .classpath
10 | .DS_Store
11 | .externalToolBuilders/
12 | .gradle/
13 | .idea/
14 | .loadpath
15 | .metadata
16 | .prefs
17 | .project
18 | .recommenders/
19 | .settings
20 | .springBeans
21 | .vertx
22 | bin/
23 | local.properties
24 | target/
25 | tmp/
26 | build/
27 | out/
28 | docker/reports/*
29 |
--------------------------------------------------------------------------------
/CLA.md:
--------------------------------------------------------------------------------
1 | Sign the CLA
2 | =============
3 |
4 | This page is the step-by-step guide to signing the Consensys Software Inc.
5 | Individual Contributor License Agreement.
6 |
7 | 1. First and foremost, read [the current version of the CLA].
8 | It is written to be as close to plain English as possible.
9 |
10 | 2. Make an account on [GitHub] if you don't already have one.
11 |
12 | 3. After creating your first pull request, you will see a merge
13 | pre-requisite requiring to you read and sign the CLA.
14 |
15 | If you have any questions, you can reach us on [Gitter].
16 |
17 | [GitHub]: https://github.com/
18 | [the current version of the CLA]: https://gist.github.com/rojotek/978b48a5e8b68836856a8961d6887992
19 |
--------------------------------------------------------------------------------
/GOVERNANCE.md:
--------------------------------------------------------------------------------
1 | # Overview
2 | This project is led by a benevolent dictator (ConsenSys) and managed by the community. That is, the
3 | community actively contributes to the day-to-day maintenance of the project, but the general
4 | strategic line is drawn by the benevolent dictator. In case of disagreement, they have the last word.
5 | It is the benevolent dictator’s job to resolve disputes within the community and to ensure that the
6 | project is able to progress in a coordinated way. In turn, it is the community’s job to guide the
7 | decisions of the benevolent dictator through active engagement and contribution.
8 |
9 |
10 | # Principles
11 |
12 | The community adheres to the following principles:
13 | * Open: Signers is open source. See repository guidelines and CLA, below.
14 | * Welcoming and respectful: See Code of Conduct, below.
15 | * Transparent and accessible: Work and collaboration should be done in public.
16 | * Merit: Ideas and contributions are accepted according to their technical merit and alignment with
17 | project objectives and design principles.
18 |
19 | # Code of Conduct
20 | See [code of conduct]
21 |
22 | # Community membership
23 |
24 | See [community membership]
25 |
26 | # Decision Making
27 | Decision making will be handled by the Approvers (see [community membership]). If consensus cannot
28 | be reached, the Benevolent Dictator will provide the final word on the decision.
29 |
30 |
31 | # CLA
32 |
33 | All contributors must sign the CLA, as described in [CLA.md].
34 | ## Attribution
35 |
36 | This document was influenced by the following:
37 | - Kubernetes community-membership.md, available at [kub community membership].
38 | - Kubernetes governance.md, available at [kub governance]
39 | - OSSWatch Benevolent Dictator Governance Model, available at [oss watch benevolent dictator].
40 |
41 | [CLA.md]: /CLA.md
42 | [code of conduct]: /CODE-OF-CONDUCT.md
43 | [oss watch benevolent dictator]: http://oss-watch.ac.uk/resources/benevolentdictatorgovernancemodel
44 | [kub community membership]: https://raw.githubusercontent.com/kubernetes/community/master/community-membership.md
45 | [kub governance]:https://github.com/kubernetes/community/blob/master/governance.md
46 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Signers
2 |
3 | ## Description
4 | A library of utilities which aid in handling keys and signing operations.
5 |
--------------------------------------------------------------------------------
/acceptance-tests/src/test/java/tech/pegasys/signers/secp256k1/tests/multikey/AzureBasedTomlLoadingAcceptanceTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.tests.multikey;
14 |
15 | import static org.assertj.core.api.Assertions.assertThat;
16 | import static tech.pegasys.signers.secp256k1.MultiKeyTomlFileUtil.createAzureTomlFileAt;
17 |
18 | import tech.pegasys.signers.secp256k1.EthPublicKeyUtils;
19 | import tech.pegasys.signers.secp256k1.common.PublicKeySignerIdentifier;
20 |
21 | import java.nio.file.Path;
22 |
23 | import org.junit.jupiter.api.Assumptions;
24 | import org.junit.jupiter.api.BeforeAll;
25 | import org.junit.jupiter.api.Test;
26 | import org.junit.jupiter.api.io.TempDir;
27 |
28 | public class AzureBasedTomlLoadingAcceptanceTest extends MultiKeyAcceptanceTestBase {
29 |
30 | static final String clientId = System.getenv("AZURE_CLIENT_ID");
31 | static final String clientSecret = System.getenv("AZURE_CLIENT_SECRET");
32 | static final String keyVaultName = System.getenv("AZURE_KEY_VAULT_NAME");
33 | static final String tenantId = System.getenv("AZURE_TENANT_ID");
34 | // TestKey2
35 | public static final String PUBLIC_KEY_HEX_STRING =
36 | "964f00253459f1f43c7a7720a0db09a328d4ee6f18838015023135d7fc921f1448de34d05de7a1f72a7b5c9f6c76931d7ab33d0f0846ccce5452063bd20f5809";
37 |
38 | @BeforeAll
39 | static void preChecks() {
40 | Assumptions.assumeTrue(
41 | clientId != null && clientSecret != null && keyVaultName != null && tenantId != null,
42 | "Ensure Azure env variables are set");
43 | }
44 |
45 | @Test
46 | void azureSignersAreCreatedAndExpectedAddressIsReported(@TempDir Path tomlDirectory) {
47 | createAzureTomlFileAt(
48 | tomlDirectory.resolve(PUBLIC_KEY_HEX_STRING + ".toml"),
49 | clientId,
50 | clientSecret,
51 | keyVaultName,
52 | tenantId);
53 |
54 | setup(tomlDirectory);
55 |
56 | assertThat(
57 | signerProvider.availablePublicKeys(PublicKeySignerIdentifier::new).stream()
58 | .map(EthPublicKeyUtils::toHexString))
59 | .containsOnly("0x" + PUBLIC_KEY_HEX_STRING);
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/acceptance-tests/src/test/java/tech/pegasys/signers/secp256k1/tests/multikey/HashicorpBasedTomlLoadingAcceptanceTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.tests.multikey;
14 |
15 | import static org.assertj.core.api.Assertions.assertThat;
16 | import static tech.pegasys.signers.secp256k1.MultiKeyTomlFileUtil.createHashicorpTomlFileAt;
17 |
18 | import tech.pegasys.signers.secp256k1.EthPublicKeyUtils;
19 | import tech.pegasys.signers.secp256k1.HashicorpSigningParams;
20 | import tech.pegasys.signers.secp256k1.common.PublicKeySignerIdentifier;
21 |
22 | import java.nio.file.Path;
23 |
24 | import org.junit.jupiter.api.AfterAll;
25 | import org.junit.jupiter.api.BeforeAll;
26 | import org.junit.jupiter.api.Test;
27 | import org.junit.jupiter.api.io.TempDir;
28 |
29 | class HashicorpBasedTomlLoadingAcceptanceTest extends MultiKeyAcceptanceTestBase {
30 |
31 | public static final String PUBLIC_KEY_HEX_STRING =
32 | "09b02f8a5fddd222ade4ea4528faefc399623af3f736be3c44f03e2df22fb792f3931a4d9573d333ca74343305762a753388c3422a86d98b713fc91c1ea04842";
33 |
34 | private static HashicorpSigningParams hashicorpNode;
35 |
36 | @BeforeAll
37 | static void setUpBase() {
38 | hashicorpNode = HashicorpHelpers.createLoadedHashicorpVault(false);
39 | }
40 |
41 | @Test
42 | void hashicorpSignerIsCreatedAndExpectedAddressIsReported(@TempDir final Path tempDir) {
43 | createHashicorpTomlFileAt(tempDir.resolve(PUBLIC_KEY_HEX_STRING + ".toml"), hashicorpNode);
44 | setup(tempDir);
45 |
46 | assertThat(
47 | signerProvider.availablePublicKeys(PublicKeySignerIdentifier::new).stream()
48 | .map(EthPublicKeyUtils::toHexString))
49 | .containsOnly("0x" + PUBLIC_KEY_HEX_STRING);
50 | }
51 |
52 | @AfterAll
53 | static void tearDown() {
54 | hashicorpNode.shutdown();
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/acceptance-tests/src/test/java/tech/pegasys/signers/secp256k1/tests/multikey/HashicorpHelpers.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.tests.multikey;
14 |
15 | import static java.util.Collections.singletonMap;
16 |
17 | import tech.pegasys.signers.hashicorp.dsl.HashicorpNode;
18 | import tech.pegasys.signers.secp256k1.HashicorpSigningParams;
19 |
20 | public class HashicorpHelpers {
21 |
22 | public static final String secretPath = "acceptanceTestSecretPath";
23 | public static final String secretName = "value";
24 | private static final String PRIVATE_KEY_HEX_STRING =
25 | "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63";
26 |
27 | public static HashicorpSigningParams createLoadedHashicorpVault(boolean useTls) {
28 | final HashicorpNode hashicorpNode = HashicorpNode.createAndStartHashicorp(useTls);
29 | hashicorpNode.addSecretsToVault(singletonMap(secretName, PRIVATE_KEY_HEX_STRING), secretPath);
30 |
31 | return new HashicorpSigningParams(hashicorpNode, secretPath, secretName);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/acceptance-tests/src/test/java/tech/pegasys/signers/secp256k1/tests/multikey/HashicorpTlsBasedTomlLoadingAcceptanceTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.tests.multikey;
14 |
15 | import static org.assertj.core.api.Assertions.assertThat;
16 | import static tech.pegasys.signers.secp256k1.MultiKeyTomlFileUtil.createHashicorpTomlFileAt;
17 |
18 | import tech.pegasys.signers.secp256k1.EthPublicKeyUtils;
19 | import tech.pegasys.signers.secp256k1.HashicorpSigningParams;
20 | import tech.pegasys.signers.secp256k1.common.PublicKeySignerIdentifier;
21 |
22 | import java.nio.file.Path;
23 | import java.util.stream.Collectors;
24 |
25 | import org.junit.jupiter.api.AfterAll;
26 | import org.junit.jupiter.api.BeforeAll;
27 | import org.junit.jupiter.api.Test;
28 | import org.junit.jupiter.api.io.TempDir;
29 | import org.web3j.utils.Numeric;
30 |
31 | class HashicorpTlsBasedTomlLoadingAcceptanceTest extends MultiKeyAcceptanceTestBase {
32 |
33 | public static final String PUBLIC_KEY_HEX_STRING =
34 | "09b02f8a5fddd222ade4ea4528faefc399623af3f736be3c44f03e2df22fb792f3931a4d9573d333ca74343305762a753388c3422a86d98b713fc91c1ea04842";
35 |
36 | private static HashicorpSigningParams hashicorpNode;
37 |
38 | @BeforeAll
39 | static void setUpBase() {
40 | hashicorpNode = HashicorpHelpers.createLoadedHashicorpVault(true);
41 | }
42 |
43 | @Test
44 | void hashicorpSignerIsCreatedAndExpectedAddressIsReported(@TempDir final Path tempDir) {
45 | createHashicorpTomlFileAt(tempDir.resolve(PUBLIC_KEY_HEX_STRING + ".toml"), hashicorpNode);
46 | setup(tempDir);
47 | assertThat(
48 | signerProvider.availablePublicKeys(PublicKeySignerIdentifier::new).stream()
49 | .map(EthPublicKeyUtils::toByteArray)
50 | .collect(Collectors.toList()))
51 | .containsOnly(Numeric.hexStringToByteArray(PUBLIC_KEY_HEX_STRING));
52 | }
53 |
54 | @AfterAll
55 | static void tearDown() {
56 | hashicorpNode.shutdown();
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/acceptance-tests/src/test/java/tech/pegasys/signers/secp256k1/tests/multikey/MultiKeyAcceptanceTestBase.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.tests.multikey;
14 |
15 | import tech.pegasys.signers.secp256k1.AllTomlConfigFilesSelector;
16 | import tech.pegasys.signers.secp256k1.SignerIdentifierConfigFileSelector;
17 | import tech.pegasys.signers.secp256k1.multikey.MultiKeySignerProvider;
18 |
19 | import java.nio.file.Path;
20 |
21 | public class MultiKeyAcceptanceTestBase {
22 |
23 | protected MultiKeySignerProvider signerProvider;
24 |
25 | protected void setup(final Path tomlDirectory) {
26 | this.signerProvider =
27 | MultiKeySignerProvider.create(
28 | tomlDirectory,
29 | new AllTomlConfigFilesSelector(),
30 | new SignerIdentifierConfigFileSelector());
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/acceptance-tests/src/test/java/tech/pegasys/signers/secp256k1/tests/multikey/signing/MultiKeyAzureTransactionSignerAcceptanceTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.tests.multikey.signing;
14 |
15 | import static tech.pegasys.signers.secp256k1.MultiKeyTomlFileUtil.createAzureTomlFileAt;
16 |
17 | import java.nio.file.Path;
18 |
19 | import org.junit.jupiter.api.Assumptions;
20 | import org.junit.jupiter.api.BeforeAll;
21 | import org.junit.jupiter.api.Test;
22 | import org.junit.jupiter.api.io.TempDir;
23 |
24 | public class MultiKeyAzureTransactionSignerAcceptanceTest
25 | extends MultiKeyTransactionSigningAcceptanceTestBase {
26 |
27 | static final String clientId = System.getenv("AZURE_CLIENT_ID");
28 | static final String clientSecret = System.getenv("AZURE_CLIENT_SECRET");
29 | static final String keyVaultName = System.getenv("AZURE_KEY_VAULT_NAME");
30 | static final String tenantId = System.getenv("AZURE_TENANT_ID");
31 | private static final String AZURE_PUBLIC_KEY_HEX_STRING =
32 | "964f00253459f1f43c7a7720a0db09a328d4ee6f18838015023135d7fc921f1448de34d05de7a1f72a7b5c9f6c76931d7ab33d0f0846ccce5452063bd20f5809";
33 |
34 | @BeforeAll
35 | static void preChecks() {
36 | Assumptions.assumeTrue(
37 | clientId != null && clientSecret != null && keyVaultName != null && tenantId != null,
38 | "Ensure Azure env variables are set");
39 | }
40 |
41 | @Test
42 | public void azureLoadedFromMultiKeyCanSign(@TempDir Path tomlDirectory) {
43 | createAzureTomlFileAt(
44 | tomlDirectory.resolve(AZURE_PUBLIC_KEY_HEX_STRING + ".toml"),
45 | clientId,
46 | clientSecret,
47 | keyVaultName,
48 | tenantId);
49 | setup(tomlDirectory);
50 | verifySignature(AZURE_PUBLIC_KEY_HEX_STRING);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/acceptance-tests/src/test/java/tech/pegasys/signers/secp256k1/tests/multikey/signing/MultiKeyFileBasedTransactionSignerAcceptanceTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.tests.multikey.signing;
14 |
15 | import static java.nio.charset.StandardCharsets.UTF_8;
16 | import static tech.pegasys.signers.secp256k1.MultiKeyTomlFileUtil.createFileBasedTomlFileAt;
17 |
18 | import java.io.File;
19 | import java.io.IOException;
20 | import java.net.URISyntaxException;
21 | import java.nio.file.Files;
22 | import java.nio.file.Path;
23 |
24 | import com.google.common.io.Resources;
25 | import org.junit.jupiter.api.Test;
26 | import org.junit.jupiter.api.io.TempDir;
27 |
28 | public class MultiKeyFileBasedTransactionSignerAcceptanceTest
29 | extends MultiKeyTransactionSigningAcceptanceTestBase {
30 |
31 | static final String FILENAME =
32 | "09b02f8a5fddd222ade4ea4528faefc399623af3f736be3c44f03e2df22fb792f3931a4d9573d333ca74343305762a753388c3422a86d98b713fc91c1ea04842";
33 |
34 | @Test
35 | public void fileBasedMultiKeyCanSign(@TempDir Path tomlDirectory)
36 | throws URISyntaxException, IOException {
37 | final String keyPath =
38 | new File(Resources.getResource("secp256k1/rich_benefactor_one.json").toURI())
39 | .getAbsolutePath();
40 |
41 | final Path passwordPath = tomlDirectory.resolve("password");
42 | Files.write(passwordPath, "pass".getBytes(UTF_8));
43 |
44 | createFileBasedTomlFileAt(
45 | tomlDirectory.resolve(FILENAME + ".toml"), keyPath, passwordPath.toString());
46 |
47 | setup(tomlDirectory);
48 | verifySignature();
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/acceptance-tests/src/test/java/tech/pegasys/signers/secp256k1/tests/multikey/signing/MultiKeyHashicorpTransactionSignerAcceptanceTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.tests.multikey.signing;
14 |
15 | import static tech.pegasys.signers.secp256k1.MultiKeyTomlFileUtil.createHashicorpTomlFileAt;
16 |
17 | import tech.pegasys.signers.secp256k1.HashicorpSigningParams;
18 | import tech.pegasys.signers.secp256k1.tests.multikey.HashicorpHelpers;
19 |
20 | import java.nio.file.Path;
21 |
22 | import org.junit.jupiter.api.AfterAll;
23 | import org.junit.jupiter.api.BeforeAll;
24 | import org.junit.jupiter.api.Test;
25 | import org.junit.jupiter.api.io.TempDir;
26 |
27 | public class MultiKeyHashicorpTransactionSignerAcceptanceTest
28 | extends MultiKeyTransactionSigningAcceptanceTestBase {
29 |
30 | static final String FILENAME =
31 | "09b02f8a5fddd222ade4ea4528faefc399623af3f736be3c44f03e2df22fb792f3931a4d9573d333ca74343305762a753388c3422a86d98b713fc91c1ea04842";
32 |
33 | private static HashicorpSigningParams hashicorpNode;
34 |
35 | @BeforeAll
36 | static void preSetup() {
37 | hashicorpNode = HashicorpHelpers.createLoadedHashicorpVault(false);
38 | }
39 |
40 | @Test
41 | void hashicorpLoadedFromMultiKeyCanSign(@TempDir Path tomlDirectory) {
42 |
43 | createHashicorpTomlFileAt(tomlDirectory.resolve(FILENAME + ".toml"), hashicorpNode);
44 |
45 | setup(tomlDirectory);
46 | verifySignature();
47 | }
48 |
49 | @AfterAll
50 | static void tearDown() {
51 | if (hashicorpNode != null) {
52 | hashicorpNode.shutdown();
53 | hashicorpNode = null;
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/acceptance-tests/src/test/resources/log4j2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | INFO
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/acceptance-tests/src/test/resources/secp256k1/UTC--2019-12-05T05-17-11.151993000Z--a01f618424b0113a9cebdc6cb66ca5b48e9120c5.key:
--------------------------------------------------------------------------------
1 | {"address":"a01f618424b0113a9cebdc6cb66ca5b48e9120c5","id":"f09c781e-a107-4e07-9079-dd755ae2267a","version":3,"crypto":{"cipher":"aes-128-ctr","ciphertext":"e577be9f433e07eb8109348eca7a971631294f984525feb4d859b5dd0dc9f17e","cipherparams":{"iv":"654ef2dd48f71afa05ccca86553c9d66"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"0f91375b7dd73aa8fd59c6dade111747eb1b1395f954e980ef7ef9d0632358a9"},"mac":"2e732f4d299100ce3df72e9b9c204f90c49f7b59996b271393e85a6dc26cf883"}}
--------------------------------------------------------------------------------
/acceptance-tests/src/test/resources/secp256k1/UTC--2019-12-05T05-17-11.151993000Z--a01f618424b0113a9cebdc6cb66ca5b48e9120c5.password:
--------------------------------------------------------------------------------
1 | password
--------------------------------------------------------------------------------
/acceptance-tests/src/test/resources/secp256k1/rich_benefactor_one.json:
--------------------------------------------------------------------------------
1 | {"address":"fe3b557e8fb62b89f4916b721be55ceb828dbd73","crypto":{"cipher":"aes-128-ctr","ciphertext":"c330870080626a6cf84c36eeb89f6376316637fbc16c86400eb6c394de5aed81","cipherparams":{"iv":"7f2526feb38ac355c644a84e78ec5692"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"b0da609bb541df918eb55bbeaf237445aa406a0c2d6e975663c4fcb221bc54e0"},"mac":"1ed0ef9e2092d0f5db8d16409ee2aaee9af3f521a5eafd910ce19dbc76e67ed7"},"id":"43f8e00a-c6ec-4a62-b7cb-f54cb299c3db","version":3}
--------------------------------------------------------------------------------
/acceptance-tests/src/testFixtures/java/tech.pegasys.signers.secp256k1/AllTomlConfigFilesSelector.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2021 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1;
14 |
15 | import tech.pegasys.signers.secp256k1.api.FileSelector;
16 |
17 | import java.nio.file.DirectoryStream;
18 | import java.nio.file.Path;
19 |
20 | public class AllTomlConfigFilesSelector implements FileSelector {
21 | @Override
22 | public DirectoryStream.Filter getConfigFilesFilter(final Void selectionCriteria) {
23 | return entry -> entry.getFileName().toString().endsWith("toml");
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/acceptance-tests/src/testFixtures/java/tech.pegasys.signers.secp256k1/HashicorpSigningParams.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1;
14 |
15 | import tech.pegasys.signers.hashicorp.dsl.HashicorpNode;
16 | import tech.pegasys.signers.hashicorp.dsl.certificates.SelfSignedCertificate;
17 |
18 | import java.util.Optional;
19 |
20 | public class HashicorpSigningParams {
21 |
22 | final HashicorpNode hashicorpNode;
23 | final String secretPath;
24 | final String secretName;
25 |
26 | public HashicorpSigningParams(
27 | final HashicorpNode hashicorpNode, final String secretPath, final String secretName) {
28 | this.hashicorpNode = hashicorpNode;
29 | this.secretPath = secretPath;
30 | this.secretName = secretName;
31 | }
32 |
33 | public int getPort() {
34 | return hashicorpNode.getPort();
35 | }
36 |
37 | public String getHost() {
38 | return hashicorpNode.getHost();
39 | }
40 |
41 | public String getVaultToken() {
42 | return hashicorpNode.getVaultToken();
43 | }
44 |
45 | public Optional getServerCertificate() {
46 | return hashicorpNode.getServerCertificate();
47 | }
48 |
49 | public String getSecretHttpPath() {
50 | return hashicorpNode.getHttpApiPathForSecret(secretPath);
51 | }
52 |
53 | public String getSecretName() {
54 | return secretName;
55 | }
56 |
57 | public void shutdown() {
58 | hashicorpNode.shutdown();
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/acceptance-tests/src/testFixtures/java/tech.pegasys.signers.secp256k1/SignerIdentifierConfigFileSelector.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2021 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1;
14 |
15 | import tech.pegasys.signers.secp256k1.api.FileSelector;
16 | import tech.pegasys.signers.secp256k1.api.SignerIdentifier;
17 |
18 | import java.nio.file.DirectoryStream;
19 | import java.nio.file.Path;
20 |
21 | public class SignerIdentifierConfigFileSelector implements FileSelector {
22 |
23 | @Override
24 | public DirectoryStream.Filter getConfigFilesFilter(
25 | final SignerIdentifier signerIdentifier) {
26 | return entry ->
27 | entry.getFileName().toString().equals(signerIdentifier.toStringIdentifier() + ".toml");
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/bls-keystore/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 |
14 | apply plugin: 'java-library'
15 |
16 | jar {
17 | archiveBaseName = "bls-keystore"
18 | manifest {
19 | attributes(
20 | 'Specification-Title': archiveBaseName.get(),
21 | 'Specification-Version': rootProject.version,
22 | 'Implementation-Title': archiveBaseName.get(),
23 | 'Implementation-Version': calculateVersion()
24 | )
25 | }
26 | }
27 |
28 | dependencies {
29 | implementation 'com.fasterxml.jackson.core:jackson-databind'
30 | implementation 'org.bouncycastle:bcprov-jdk15on'
31 | implementation 'com.google.guava:guava'
32 | implementation 'org.apache.logging.log4j:log4j-api'
33 | implementation 'org.apache.tuweni:tuweni-bytes'
34 | implementation 'org.apache.tuweni:tuweni-crypto'
35 |
36 | testImplementation 'org.assertj:assertj-core'
37 | testImplementation 'org.junit.jupiter:junit-jupiter-engine'
38 | testImplementation 'org.junit.jupiter:junit-jupiter-api'
39 | testImplementation 'org.junit.jupiter:junit-jupiter-params'
40 | testImplementation 'org.mockito:mockito-core'
41 | testImplementation 'org.mockito:mockito-junit-jupiter'
42 | }
43 |
--------------------------------------------------------------------------------
/bls-keystore/src/main/java/tech/pegasys/signers/bls/keystore/KeyStoreValidationException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.bls.keystore;
14 |
15 | public class KeyStoreValidationException extends RuntimeException {
16 | public KeyStoreValidationException() {
17 | super();
18 | }
19 |
20 | public KeyStoreValidationException(final String message) {
21 | super(message);
22 | }
23 |
24 | public KeyStoreValidationException(final String message, final Throwable cause) {
25 | super(message, cause);
26 | }
27 |
28 | public KeyStoreValidationException(final Throwable cause) {
29 | super(cause);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/bls-keystore/src/main/java/tech/pegasys/signers/bls/keystore/PasswordUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.bls.keystore;
14 |
15 | import static java.nio.charset.StandardCharsets.UTF_8;
16 |
17 | import java.text.Normalizer;
18 | import java.text.Normalizer.Form;
19 |
20 | import org.apache.tuweni.bytes.Bytes;
21 |
22 | public class PasswordUtils {
23 |
24 | public static Bytes normalizePassword(final String password) {
25 | final String normalizedPassword = Normalizer.normalize(password, Form.NFKD);
26 | final int[] filteredCodepoints =
27 | normalizedPassword.chars().filter(c -> !isControlCode(c)).toArray();
28 | final byte[] utf8Password =
29 | new String(filteredCodepoints, 0, filteredCodepoints.length).getBytes(UTF_8);
30 | return Bytes.wrap(utf8Password);
31 | }
32 |
33 | private static boolean isControlCode(final int c) {
34 | return isC0(c) || isC1(c) || c == 0x7F;
35 | }
36 |
37 | private static boolean isC1(final int c) {
38 | return 0x80 <= c && c <= 0x9F;
39 | }
40 |
41 | private static boolean isC0(final int c) {
42 | return 0x00 <= c && c <= 0x1F;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/bls-keystore/src/main/java/tech/pegasys/signers/bls/keystore/model/Checksum.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.bls.keystore.model;
14 |
15 | import com.fasterxml.jackson.annotation.JsonCreator;
16 | import com.fasterxml.jackson.annotation.JsonProperty;
17 | import com.google.common.base.MoreObjects;
18 | import org.apache.tuweni.bytes.Bytes;
19 |
20 | public class Checksum {
21 | private final ChecksumFunction checksumFunction;
22 | private final EmptyParam emptyParam;
23 | private final Bytes message;
24 |
25 | @JsonCreator
26 | public Checksum(
27 | @JsonProperty(value = "function", required = true) final ChecksumFunction checksumFunction,
28 | @JsonProperty(value = "params", required = true) final EmptyParam emptyParam,
29 | @JsonProperty(value = "message", required = true) final Bytes message) {
30 | this.checksumFunction = checksumFunction;
31 | this.emptyParam = emptyParam;
32 | this.message = message;
33 | }
34 |
35 | public Checksum(final Bytes message) {
36 | this(ChecksumFunction.SHA256, new EmptyParam(), message);
37 | }
38 |
39 | @JsonProperty(value = "function")
40 | public ChecksumFunction getChecksumFunction() {
41 | return checksumFunction;
42 | }
43 |
44 | @JsonProperty(value = "params")
45 | public EmptyParam getEmptyParam() {
46 | return emptyParam;
47 | }
48 |
49 | @JsonProperty(value = "message")
50 | public Bytes getMessage() {
51 | return message;
52 | }
53 |
54 | @Override
55 | public String toString() {
56 | return MoreObjects.toStringHelper(this)
57 | .add("function", checksumFunction)
58 | .add("param", emptyParam)
59 | .add("message", message)
60 | .toString();
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/bls-keystore/src/main/java/tech/pegasys/signers/bls/keystore/model/ChecksumFunction.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.bls.keystore.model;
14 |
15 | import com.fasterxml.jackson.annotation.JsonValue;
16 |
17 | public enum ChecksumFunction {
18 | SHA256("sha256");
19 | private final String jsonValue;
20 |
21 | ChecksumFunction(final String jsonValue) {
22 | this.jsonValue = jsonValue;
23 | }
24 |
25 | @JsonValue
26 | public String getJsonValue() {
27 | return this.jsonValue;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/bls-keystore/src/main/java/tech/pegasys/signers/bls/keystore/model/Cipher.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.bls.keystore.model;
14 |
15 | import tech.pegasys.signers.bls.keystore.KeyStoreValidationException;
16 |
17 | import com.fasterxml.jackson.annotation.JsonCreator;
18 | import com.fasterxml.jackson.annotation.JsonProperty;
19 | import com.google.common.base.MoreObjects;
20 | import org.apache.tuweni.bytes.Bytes;
21 |
22 | public class Cipher {
23 | private final CipherFunction cipherFunction;
24 | private final CipherParam cipherParam;
25 | private final Bytes message;
26 |
27 | @JsonCreator
28 | public Cipher(
29 | @JsonProperty(value = "function", required = true) final CipherFunction cipherFunction,
30 | @JsonProperty(value = "params", required = true) final CipherParam cipherParam,
31 | @JsonProperty(value = "message", required = true) final Bytes message) {
32 | this.cipherFunction = cipherFunction;
33 | this.cipherParam = cipherParam;
34 | this.message = message;
35 | }
36 |
37 | public Cipher(final CipherFunction cipherFunction, final Bytes ivParam) {
38 | this(cipherFunction, new CipherParam(ivParam), Bytes.EMPTY);
39 | }
40 |
41 | public Cipher(final Bytes ivParam) {
42 | this(CipherFunction.AES_128_CTR, new CipherParam(ivParam), Bytes.EMPTY);
43 | }
44 |
45 | @JsonProperty(value = "function")
46 | public CipherFunction getCipherFunction() {
47 | return cipherFunction;
48 | }
49 |
50 | @JsonProperty(value = "params")
51 | public CipherParam getCipherParam() {
52 | return cipherParam;
53 | }
54 |
55 | @JsonProperty(value = "message")
56 | public Bytes getMessage() {
57 | return message;
58 | }
59 |
60 | public void validate() throws KeyStoreValidationException {
61 | // In case of CTR/SIC, the size of IV is between 8 bytes and 16 bytes
62 | if (cipherParam.getIv().size() < 8 || cipherParam.getIv().size() > 16) {
63 | throw new KeyStoreValidationException(
64 | "Initialization Vector parameter iv size must be >= 8 and <= 16");
65 | }
66 | }
67 |
68 | @Override
69 | public String toString() {
70 | return MoreObjects.toStringHelper(this)
71 | .add("function", cipherFunction)
72 | .add("params", cipherParam)
73 | .add("message", message)
74 | .toString();
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/bls-keystore/src/main/java/tech/pegasys/signers/bls/keystore/model/CipherFunction.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.bls.keystore.model;
14 |
15 | import com.fasterxml.jackson.annotation.JsonValue;
16 |
17 | public enum CipherFunction {
18 | AES_128_CTR("aes-128-ctr");
19 |
20 | private final String jsonValue;
21 |
22 | CipherFunction(final String jsonValue) {
23 | this.jsonValue = jsonValue;
24 | }
25 |
26 | @JsonValue
27 | public String getJsonValue() {
28 | return this.jsonValue;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/bls-keystore/src/main/java/tech/pegasys/signers/bls/keystore/model/CipherParam.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.bls.keystore.model;
14 |
15 | import com.fasterxml.jackson.annotation.JsonCreator;
16 | import com.fasterxml.jackson.annotation.JsonProperty;
17 | import com.google.common.base.MoreObjects;
18 | import org.apache.tuweni.bytes.Bytes;
19 |
20 | public class CipherParam {
21 | private final Bytes iv;
22 |
23 | @JsonCreator
24 | public CipherParam(@JsonProperty(value = "iv", required = true) final Bytes iv) {
25 | this.iv = iv;
26 | }
27 |
28 | @JsonProperty(value = "iv")
29 | public Bytes getIv() {
30 | return iv;
31 | }
32 |
33 | @Override
34 | public String toString() {
35 | return MoreObjects.toStringHelper(this).add("iv", iv).toString();
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/bls-keystore/src/main/java/tech/pegasys/signers/bls/keystore/model/Crypto.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.bls.keystore.model;
14 |
15 | import com.fasterxml.jackson.annotation.JsonCreator;
16 | import com.fasterxml.jackson.annotation.JsonProperty;
17 | import com.google.common.base.MoreObjects;
18 |
19 | public class Crypto {
20 | private final Kdf kdf;
21 | private final Checksum checksum;
22 | private final Cipher cipher;
23 |
24 | @JsonCreator
25 | public Crypto(
26 | @JsonProperty(value = "kdf", required = true) final Kdf kdf,
27 | @JsonProperty(value = "checksum", required = true) final Checksum checksum,
28 | @JsonProperty(value = "cipher", required = true) final Cipher cipher) {
29 | this.kdf = kdf;
30 | this.checksum = checksum;
31 | this.cipher = cipher;
32 | }
33 |
34 | @JsonProperty(value = "kdf")
35 | public Kdf getKdf() {
36 | return kdf;
37 | }
38 |
39 | @JsonProperty(value = "checksum")
40 | public Checksum getChecksum() {
41 | return checksum;
42 | }
43 |
44 | @JsonProperty(value = "cipher")
45 | public Cipher getCipher() {
46 | return cipher;
47 | }
48 |
49 | public void validate() {
50 | kdf.validate();
51 | cipher.validate();
52 | }
53 |
54 | @Override
55 | public String toString() {
56 | return MoreObjects.toStringHelper(this)
57 | .add("kdf", kdf)
58 | .add("checksum", checksum)
59 | .add("cipher", cipher)
60 | .toString();
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/bls-keystore/src/main/java/tech/pegasys/signers/bls/keystore/model/EmptyParam.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.bls.keystore.model;
14 |
15 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
16 |
17 | /** Placeholder for empty params */
18 | @JsonIgnoreProperties(ignoreUnknown = true)
19 | public class EmptyParam {
20 | public EmptyParam() {}
21 |
22 | @Override
23 | public String toString() {
24 | return "";
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/bls-keystore/src/main/java/tech/pegasys/signers/bls/keystore/model/Kdf.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.bls.keystore.model;
14 |
15 | import tech.pegasys.signers.bls.keystore.KeyStoreValidationException;
16 |
17 | import com.fasterxml.jackson.annotation.JsonCreator;
18 | import com.fasterxml.jackson.annotation.JsonProperty;
19 | import com.fasterxml.jackson.annotation.JsonSubTypes;
20 | import com.fasterxml.jackson.annotation.JsonTypeInfo;
21 | import com.google.common.base.MoreObjects;
22 |
23 | public class Kdf {
24 | private final KdfFunction kdfFunction;
25 | private final KdfParam param;
26 | private final String message;
27 |
28 | @JsonCreator
29 | public Kdf(
30 | @JsonProperty(value = "function", required = true) final KdfFunction kdfFunction,
31 | @JsonProperty(value = "params", required = true)
32 | @JsonTypeInfo(
33 | use = JsonTypeInfo.Id.NAME,
34 | include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
35 | property = "function")
36 | @JsonSubTypes({
37 | @JsonSubTypes.Type(value = SCryptParam.class, name = "scrypt"),
38 | @JsonSubTypes.Type(value = Pbkdf2Param.class, name = "pbkdf2")
39 | })
40 | final KdfParam param,
41 | @JsonProperty(value = "message", required = true) final String message) {
42 | this.kdfFunction = kdfFunction;
43 | this.param = param;
44 | this.message = message;
45 | }
46 |
47 | public Kdf(final KdfParam kdfParam) {
48 | this(kdfParam.getKdfFunction(), kdfParam, "");
49 | }
50 |
51 | @JsonProperty(value = "function")
52 | public KdfFunction getKdfFunction() {
53 | return kdfFunction;
54 | }
55 |
56 | @JsonProperty(value = "params")
57 | public KdfParam getParam() {
58 | return param;
59 | }
60 |
61 | @JsonProperty(value = "message")
62 | public String getMessage() {
63 | return message;
64 | }
65 |
66 | public void validate() throws KeyStoreValidationException {
67 | param.validate();
68 | }
69 |
70 | @Override
71 | public String toString() {
72 | return MoreObjects.toStringHelper(this)
73 | .add("function", kdfFunction)
74 | .add("params", param)
75 | .add("message", message)
76 | .toString();
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/bls-keystore/src/main/java/tech/pegasys/signers/bls/keystore/model/KdfFunction.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.bls.keystore.model;
14 |
15 | import com.fasterxml.jackson.annotation.JsonValue;
16 |
17 | public enum KdfFunction {
18 | PBKDF2("pbkdf2"),
19 | SCRYPT("scrypt");
20 |
21 | private final String jsonValue;
22 |
23 | KdfFunction(final String jsonValue) {
24 | this.jsonValue = jsonValue;
25 | }
26 |
27 | @JsonValue
28 | public String getJsonValue() {
29 | return this.jsonValue;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/bls-keystore/src/main/java/tech/pegasys/signers/bls/keystore/model/KdfParam.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.bls.keystore.model;
14 |
15 | import static com.google.common.base.Preconditions.checkNotNull;
16 |
17 | import tech.pegasys.signers.bls.keystore.KeyStoreValidationException;
18 | import tech.pegasys.signers.bls.keystore.PasswordUtils;
19 |
20 | import com.fasterxml.jackson.annotation.JsonProperty;
21 | import com.google.common.base.MoreObjects;
22 | import org.apache.tuweni.bytes.Bytes;
23 |
24 | public abstract class KdfParam {
25 | private final Integer dklen;
26 | private final Bytes salt;
27 |
28 | public KdfParam(final Integer dklen, final Bytes salt) {
29 | this.dklen = dklen;
30 | this.salt = salt;
31 | }
32 |
33 | @JsonProperty(value = "dklen")
34 | public Integer getDkLen() {
35 | return dklen;
36 | }
37 |
38 | public abstract KdfFunction getKdfFunction();
39 |
40 | public Bytes generateDecryptionKey(final String password) {
41 | return generateDecryptionKey(PasswordUtils.normalizePassword(password));
42 | }
43 |
44 | protected abstract Bytes generateDecryptionKey(final Bytes password);
45 |
46 | public void validate() {
47 | checkNotNull(getSalt(), "salt cannot be null");
48 | // because the EIP-2335 spec requires dklen >= 32
49 | if (dklen < 32) {
50 | throw new KeyStoreValidationException("Generated key length parameter dklen must be >= 32.");
51 | }
52 | }
53 |
54 | @JsonProperty(value = "salt")
55 | public Bytes getSalt() {
56 | return salt;
57 | }
58 |
59 | @Override
60 | public String toString() {
61 | return MoreObjects.toStringHelper(this).add("dklen", dklen).add("salt", salt).toString();
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/bls-keystore/src/main/java/tech/pegasys/signers/bls/keystore/model/Pbkdf2PseudoRandomFunction.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.bls.keystore.model;
14 |
15 | import com.fasterxml.jackson.annotation.JsonValue;
16 |
17 | public enum Pbkdf2PseudoRandomFunction {
18 | HMAC_SHA256("hmac-sha256");
19 | private final String jsonValue;
20 |
21 | Pbkdf2PseudoRandomFunction(final String jsonValue) {
22 | this.jsonValue = jsonValue;
23 | }
24 |
25 | @JsonValue
26 | public String getJsonValue() {
27 | return this.jsonValue;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/bls-keystore/src/test/java/tech/pegasys/signers/bls/keystore/DecryptionKeyTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.bls.keystore;
14 |
15 | import static org.assertj.core.api.Assertions.assertThat;
16 |
17 | import tech.pegasys.signers.bls.keystore.model.Pbkdf2Param;
18 | import tech.pegasys.signers.bls.keystore.model.Pbkdf2PseudoRandomFunction;
19 | import tech.pegasys.signers.bls.keystore.model.SCryptParam;
20 |
21 | import org.apache.tuweni.bytes.Bytes;
22 | import org.junit.jupiter.api.Test;
23 |
24 | class DecryptionKeyTest {
25 | private static final int DKLEN = 32;
26 | private static final int ITERATIVE_COUNT = 262144;
27 | private static final int MEMORY_CPU_COST = 262144;
28 | private static final int PARALLELIZATION = 1;
29 | private static final int BLOCKSIZE = 8;
30 | private static final Bytes SALT =
31 | Bytes.fromHexString("d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3");
32 | private static final Bytes SCRYPT_DERIVED_KEY =
33 | Bytes.fromHexString("0xBC21AF552ED055E3B3F35A39AFD8355903CA2770709B5E5B363647FA75234344");
34 | private static final Bytes PBKDF2_DERIVED_KEY =
35 | Bytes.fromHexString("0x57E2285C828F4F6B95DEEC3BB6D9D90933042C63FC9BADE14EA280202A17142D");
36 | private static final String PASSWORD = "testpassword";
37 |
38 | @Test
39 | void sCryptDecryptionKeyGeneration() {
40 | final SCryptParam kdfParam =
41 | new SCryptParam(DKLEN, MEMORY_CPU_COST, PARALLELIZATION, BLOCKSIZE, SALT);
42 | final Bytes decryptionKey = kdfParam.generateDecryptionKey(PASSWORD);
43 | assertThat(decryptionKey.size()).isEqualTo(DKLEN);
44 | assertThat(decryptionKey).isEqualTo(SCRYPT_DERIVED_KEY);
45 | }
46 |
47 | @Test
48 | void pbkdf2DecryptionKeyGeneration() {
49 | final Pbkdf2Param kdfParam =
50 | new Pbkdf2Param(DKLEN, ITERATIVE_COUNT, Pbkdf2PseudoRandomFunction.HMAC_SHA256, SALT);
51 | final Bytes decryptionKey = kdfParam.generateDecryptionKey(PASSWORD);
52 | assertThat(decryptionKey.size()).isEqualTo(DKLEN);
53 | assertThat(decryptionKey).isEqualTo(PBKDF2_DERIVED_KEY);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/bls-keystore/src/test/java/tech/pegasys/signers/bls/keystore/PasswordUtilsTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.bls.keystore;
14 |
15 | import static java.nio.charset.StandardCharsets.UTF_8;
16 | import static org.assertj.core.api.Assertions.assertThat;
17 | import static tech.pegasys.signers.bls.keystore.PasswordUtils.normalizePassword;
18 |
19 | import org.apache.tuweni.bytes.Bytes;
20 | import org.junit.jupiter.api.Test;
21 |
22 | class PasswordUtilsTest {
23 | @Test
24 | void shouldLeaveSimplePasswordUnchanged() {
25 | assertThat(normalizePassword("testpassword")).isEqualTo(utf8("testpassword"));
26 | }
27 |
28 | @Test
29 | void shouldStripControlCharactersFromPassword() {
30 | assertThat(normalizePassword("\u0000\u001F\u0080\u009Ftest \n\f\tpass\u007Fword\n"))
31 | .isEqualTo(utf8("test password"));
32 | }
33 |
34 | @Test
35 | void shouldDecodePasswordFromEip2335() {
36 | final String password =
37 | "\uD835\uDD31\uD835\uDD22\uD835\uDD30\uD835\uDD31\uD835\uDD2D\uD835\uDD1E\uD835\uDD30\uD835\uDD30\uD835\uDD34\uD835\uDD2C\uD835\uDD2F\uD835\uDD21\uD83D\uDD11";
38 | assertThat(normalizePassword(password))
39 | .isEqualTo(Bytes.fromHexString("0x7465737470617373776f7264f09f9491"));
40 | }
41 |
42 | private Bytes utf8(final String password) {
43 | return Bytes.wrap(password.getBytes(UTF_8));
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/bls-keystore/src/test/java/tech/pegasys/signers/bls/keystore/model/CipherTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.bls.keystore.model;
14 |
15 | import static org.assertj.core.api.Assertions.assertThatCode;
16 | import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
17 |
18 | import tech.pegasys.signers.bls.keystore.KeyStoreValidationException;
19 |
20 | import org.apache.tuweni.bytes.Bytes;
21 | import org.junit.jupiter.params.ParameterizedTest;
22 | import org.junit.jupiter.params.provider.ValueSource;
23 |
24 | class CipherTest {
25 | @ParameterizedTest
26 | @ValueSource(ints = {7, 17})
27 | void cipherWithInvalidIvLengthThrowsException(final int bytesSize) {
28 | assertThatExceptionOfType(KeyStoreValidationException.class)
29 | .isThrownBy(new Cipher(Bytes.random(bytesSize))::validate)
30 | .withMessage("Initialization Vector parameter iv size must be >= 8 and <= 16");
31 | }
32 |
33 | @ParameterizedTest
34 | @ValueSource(ints = {8, 16})
35 | void cipherWithValidIvLengthValidateDoesNotThrowException(final int bytesSize) {
36 | assertThatCode(new Cipher(Bytes.random(bytesSize))::validate).doesNotThrowAnyException();
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/bls-keystore/src/test/resources/missingKdfSectionTestVector.json:
--------------------------------------------------------------------------------
1 | {
2 | "crypto": {
3 | "kdf": {
4 | "function": "scrypt",
5 | "message": ""
6 | },
7 | "checksum": {
8 | "function": "sha256",
9 | "params": {},
10 | "message": "149aafa27b041f3523c53d7acba1905fa6b1c90f9fef137568101f44b531a3cb"
11 | },
12 | "cipher": {
13 | "function": "aes-128-ctr",
14 | "params": {
15 | "iv": "264daa3f303d7259501c93d997d84fe6"
16 | },
17 | "message": "54ecc8863c0550351eee5720f3be6a5d4a016025aa91cd6436cfec938d6a8d30"
18 | }
19 | },
20 | "pubkey": "9612d7a727c9d0a22e185a1c768478dfe919cada9266988cb32359c11f2b7b27f4ae4040902382ae2910c15e2b420d07",
21 | "path": "m/12381/60/3141592653/589793238",
22 | "uuid": "1d85ae20-35c5-4611-98e8-aa14a633906f",
23 | "version": 4
24 | }
--------------------------------------------------------------------------------
/bls-keystore/src/test/resources/pbkdf2TestVector.json:
--------------------------------------------------------------------------------
1 | {
2 | "crypto": {
3 | "kdf": {
4 | "function": "pbkdf2",
5 | "params": {
6 | "dklen": 32,
7 | "c": 262144,
8 | "prf": "hmac-sha256",
9 | "salt": "d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"
10 | },
11 | "message": ""
12 | },
13 | "checksum": {
14 | "function": "sha256",
15 | "params": {},
16 | "message": "8a9f5d9912ed7e75ea794bc5a89bca5f193721d30868ade6f73043c6ea6febf1"
17 | },
18 | "cipher": {
19 | "function": "aes-128-ctr",
20 | "params": {
21 | "iv": "264daa3f303d7259501c93d997d84fe6"
22 | },
23 | "message": "cee03fde2af33149775b7223e7845e4fb2c8ae1792e5f99fe9ecf474cc8c16ad"
24 | }
25 | },
26 | "description": "This is a test keystore that uses PBKDF2 to secure the secret.",
27 | "pubkey": "9612d7a727c9d0a22e185a1c768478dfe919cada9266988cb32359c11f2b7b27f4ae4040902382ae2910c15e2b420d07",
28 | "path": "m/12381/60/0/0",
29 | "uuid": "64625def-3331-4eea-ab6f-782f3ed16a83",
30 | "version": 4
31 | }
--------------------------------------------------------------------------------
/bls-keystore/src/test/resources/scryptExtraFieldTestVector.json:
--------------------------------------------------------------------------------
1 | {
2 | "crypto": {
3 | "kdf": {
4 | "function": "scrypt",
5 | "params": {
6 | "dklen": 32,
7 | "n": 262144,
8 | "p": 1,
9 | "r": 8,
10 | "salt": "d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"
11 | },
12 | "message": ""
13 | },
14 | "checksum": {
15 | "function": "sha256",
16 | "params": {},
17 | "message": "d2217fe5f3e9a1e34581ef8a78f7c9928e436d36dacc5e846690a5581e8ea484"
18 | },
19 | "cipher": {
20 | "function": "aes-128-ctr",
21 | "params": {
22 | "iv": "264daa3f303d7259501c93d997d84fe6"
23 | },
24 | "message": "06ae90d55fe0a6e9c5c3bc5b170827b2e5cce3929ed3f116c2811e6366dfe20f"
25 | }
26 | },
27 | "pubkey": "9612d7a727c9d0a22e185a1c768478dfe919cada9266988cb32359c11f2b7b27f4ae4040902382ae2910c15e2b420d07",
28 | "path": "m/12381/60/3141592653/589793238",
29 | "uuid": "1d85ae20-35c5-4611-98e8-aa14a633906f",
30 | "name": "Test",
31 | "version": 4
32 | }
--------------------------------------------------------------------------------
/bls-keystore/src/test/resources/scryptTestVector.json:
--------------------------------------------------------------------------------
1 | {
2 | "crypto": {
3 | "kdf": {
4 | "function": "scrypt",
5 | "params": {
6 | "dklen": 32,
7 | "n": 262144,
8 | "p": 1,
9 | "r": 8,
10 | "salt": "d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"
11 | },
12 | "message": ""
13 | },
14 | "checksum": {
15 | "function": "sha256",
16 | "params": {},
17 | "message": "d2217fe5f3e9a1e34581ef8a78f7c9928e436d36dacc5e846690a5581e8ea484"
18 | },
19 | "cipher": {
20 | "function": "aes-128-ctr",
21 | "params": {
22 | "iv": "264daa3f303d7259501c93d997d84fe6"
23 | },
24 | "message": "06ae90d55fe0a6e9c5c3bc5b170827b2e5cce3929ed3f116c2811e6366dfe20f"
25 | }
26 | },
27 | "description": "This is a test keystore that uses scrypt to secure the secret.",
28 | "pubkey": "9612d7a727c9d0a22e185a1c768478dfe919cada9266988cb32359c11f2b7b27f4ae4040902382ae2910c15e2b420d07",
29 | "path": "m/12381/60/3141592653/589793238",
30 | "uuid": "1d85ae20-35c5-4611-98e8-aa14a633906f",
31 | "version": 4
32 | }
--------------------------------------------------------------------------------
/bls-keystore/src/test/resources/scryptTestVectorWithMissingPathAndUUID.json:
--------------------------------------------------------------------------------
1 | {
2 | "crypto": {
3 | "kdf": {
4 | "function": "scrypt",
5 | "params": {
6 | "dklen": 32,
7 | "n": 262144,
8 | "p": 1,
9 | "r": 8,
10 | "salt": "d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"
11 | },
12 | "message": ""
13 | },
14 | "checksum": {
15 | "function": "sha256",
16 | "params": {},
17 | "message": "d2217fe5f3e9a1e34581ef8a78f7c9928e436d36dacc5e846690a5581e8ea484"
18 | },
19 | "cipher": {
20 | "function": "aes-128-ctr",
21 | "params": {
22 | "iv": "264daa3f303d7259501c93d997d84fe6"
23 | },
24 | "message": "06ae90d55fe0a6e9c5c3bc5b170827b2e5cce3929ed3f116c2811e6366dfe20f"
25 | }
26 | },
27 | "description": "This is a test keystore that uses scrypt to secure the secret.",
28 | "pubkey": "9612d7a727c9d0a22e185a1c768478dfe919cada9266988cb32359c11f2b7b27f4ae4040902382ae2910c15e2b420d07",
29 | "version": 4
30 | }
--------------------------------------------------------------------------------
/bls-keystore/src/test/resources/unsupportedChecksumFunction.json:
--------------------------------------------------------------------------------
1 | {
2 | "crypto": {
3 | "kdf": {
4 | "function": "scrypt",
5 | "params": {
6 | "dklen": 32,
7 | "n": 262144,
8 | "p": 1,
9 | "r": 8,
10 | "salt": "d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"
11 | },
12 | "message": ""
13 | },
14 | "checksum": {
15 | "function": "sha128",
16 | "params": {},
17 | "message": "149aafa27b041f3523c53d7acba1905fa6b1c90f9fef137568101f44b531a3cb"
18 | },
19 | "cipher": {
20 | "function": "aes-128-ctr",
21 | "params": {
22 | "iv": "264daa3f303d7259501c93d997d84fe6"
23 | },
24 | "message": "54ecc8863c0550351eee5720f3be6a5d4a016025aa91cd6436cfec938d6a8d30"
25 | }
26 | },
27 | "pubkey": "9612d7a727c9d0a22e185a1c768478dfe919cada9266988cb32359c11f2b7b27f4ae4040902382ae2910c15e2b420d07",
28 | "path": "m/12381/60/3141592653/589793238",
29 | "uuid": "1d85ae20-35c5-4611-98e8-aa14a633906f",
30 | "version": 4
31 | }
--------------------------------------------------------------------------------
/bls-keystore/src/test/resources/unsupportedCipherFunction.json:
--------------------------------------------------------------------------------
1 | {
2 | "crypto": {
3 | "kdf": {
4 | "function": "scrypt",
5 | "params": {
6 | "dklen": 32,
7 | "n": 262144,
8 | "p": 1,
9 | "r": 8,
10 | "salt": "d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"
11 | },
12 | "message": ""
13 | },
14 | "checksum": {
15 | "function": "sha256",
16 | "params": {},
17 | "message": "149aafa27b041f3523c53d7acba1905fa6b1c90f9fef137568101f44b531a3cb"
18 | },
19 | "cipher": {
20 | "function": "aes-256-ctr",
21 | "params": {
22 | "iv": "264daa3f303d7259501c93d997d84fe6"
23 | },
24 | "message": "54ecc8863c0550351eee5720f3be6a5d4a016025aa91cd6436cfec938d6a8d30"
25 | }
26 | },
27 | "pubkey": "9612d7a727c9d0a22e185a1c768478dfe919cada9266988cb32359c11f2b7b27f4ae4040902382ae2910c15e2b420d07",
28 | "path": "m/12381/60/3141592653/589793238",
29 | "uuid": "1d85ae20-35c5-4611-98e8-aa14a633906f",
30 | "version": 4
31 | }
--------------------------------------------------------------------------------
/bls-keystore/src/test/resources/unsupportedDkLen.json:
--------------------------------------------------------------------------------
1 | {
2 | "crypto": {
3 | "kdf": {
4 | "function": "scrypt",
5 | "params": {
6 | "dklen": 31,
7 | "n": 262144,
8 | "p": 1,
9 | "r": 8,
10 | "salt": "d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"
11 | },
12 | "message": ""
13 | },
14 | "checksum": {
15 | "function": "sha256",
16 | "params": {},
17 | "message": "149aafa27b041f3523c53d7acba1905fa6b1c90f9fef137568101f44b531a3cb"
18 | },
19 | "cipher": {
20 | "function": "aes-128-ctr",
21 | "params": {
22 | "iv": "264daa3f303d7259501c93d997d84fe6"
23 | },
24 | "message": "54ecc8863c0550351eee5720f3be6a5d4a016025aa91cd6436cfec938d6a8d30"
25 | }
26 | },
27 | "pubkey": "9612d7a727c9d0a22e185a1c768478dfe919cada9266988cb32359c11f2b7b27f4ae4040902382ae2910c15e2b420d07",
28 | "path": "m/12381/60/3141592653/589793238",
29 | "uuid": "1d85ae20-35c5-4611-98e8-aa14a633906f",
30 | "version": 4
31 | }
--------------------------------------------------------------------------------
/bls-keystore/src/test/resources/unsupportedKdfFunction.json:
--------------------------------------------------------------------------------
1 | {
2 | "crypto": {
3 | "kdf": {
4 | "function": "pbkdf3",
5 | "params": {
6 | "dklen": 32,
7 | "n": 262144,
8 | "p": 1,
9 | "r": 8,
10 | "salt": "d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"
11 | },
12 | "message": ""
13 | },
14 | "checksum": {
15 | "function": "sha256",
16 | "params": {},
17 | "message": "149aafa27b041f3523c53d7acba1905fa6b1c90f9fef137568101f44b531a3cb"
18 | },
19 | "cipher": {
20 | "function": "aes-128-ctr",
21 | "params": {
22 | "iv": "264daa3f303d7259501c93d997d84fe6"
23 | },
24 | "message": "54ecc8863c0550351eee5720f3be6a5d4a016025aa91cd6436cfec938d6a8d30"
25 | }
26 | },
27 | "pubkey": "9612d7a727c9d0a22e185a1c768478dfe919cada9266988cb32359c11f2b7b27f4ae4040902382ae2910c15e2b420d07",
28 | "path": "m/12381/60/3141592653/589793238",
29 | "uuid": "1d85ae20-35c5-4611-98e8-aa14a633906f",
30 | "version": 4
31 | }
--------------------------------------------------------------------------------
/bls-keystore/src/test/resources/unsupportedPBKDF2Prf.json:
--------------------------------------------------------------------------------
1 | {
2 | "crypto": {
3 | "kdf": {
4 | "function": "pbkdf2",
5 | "params": {
6 | "dklen": 32,
7 | "c": 262144,
8 | "prf": "hmac-sha512",
9 | "salt": "d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"
10 | },
11 | "message": ""
12 | },
13 | "checksum": {
14 | "function": "sha256",
15 | "params": {},
16 | "message": "18b148af8e52920318084560fd766f9d09587b4915258dec0676cba5b0da09d8"
17 | },
18 | "cipher": {
19 | "function": "aes-128-ctr",
20 | "params": {
21 | "iv": "264daa3f303d7259501c93d997d84fe6"
22 | },
23 | "message": "a9249e0ca7315836356e4c7440361ff22b9fe71e2e2ed34fc1eb03976924ed48"
24 | }
25 | },
26 | "pubkey": "9612d7a727c9d0a22e185a1c768478dfe919cada9266988cb32359c11f2b7b27f4ae4040902382ae2910c15e2b420d07",
27 | "path": "m/12381/60/0/0",
28 | "uuid": "64625def-3331-4eea-ab6f-782f3ed16a83",
29 | "version": 4
30 | }
--------------------------------------------------------------------------------
/bls-keystore/src/test/resources/v3TestVector.json:
--------------------------------------------------------------------------------
1 | {
2 | "crypto": {
3 | "kdf": {
4 | "function": "scrypt",
5 | "params": {
6 | "dklen": 32,
7 | "n": 262144,
8 | "p": 1,
9 | "r": 8,
10 | "salt": "d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"
11 | },
12 | "message": ""
13 | },
14 | "checksum": {
15 | "function": "sha256",
16 | "params": {},
17 | "message": "149aafa27b041f3523c53d7acba1905fa6b1c90f9fef137568101f44b531a3cb"
18 | },
19 | "cipher": {
20 | "function": "aes-128-ctr",
21 | "params": {
22 | "iv": "264daa3f303d7259501c93d997d84fe6"
23 | },
24 | "message": "54ecc8863c0550351eee5720f3be6a5d4a016025aa91cd6436cfec938d6a8d30"
25 | }
26 | },
27 | "pubkey": "9612d7a727c9d0a22e185a1c768478dfe919cada9266988cb32359c11f2b7b27f4ae4040902382ae2910c15e2b420d07",
28 | "path": "m/12381/60/3141592653/589793238",
29 | "uuid": "1d85ae20-35c5-4611-98e8-aa14a633906f",
30 | "version": 3
31 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Set exports/opens flags required by Google Java Format and ErrorProne plugins. (JEP-396)
2 | org.gradle.jvmargs=-Xmx1g \
3 | --add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \
4 | --add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED \
5 | --add-exports jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED \
6 | --add-exports jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED \
7 | --add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED \
8 | --add-exports jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED \
9 | --add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED \
10 | --add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED \
11 | --add-exports java.base/sun.security.x509=ALL-UNNAMED \
12 | --add-opens jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED \
13 | --add-opens jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED \
14 | --add-opens jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED
15 | hashicorpVaultVersion=1.9.2
16 | hashicorpVaultUrl=https://releases.hashicorp.com/vault
17 |
--------------------------------------------------------------------------------
/gradle/formatter.properties:
--------------------------------------------------------------------------------
1 | #Whether to use 'space', 'tab' or 'mixed' (both) characters for indentation.
2 | #The default value is 'tab'.
3 | org.eclipse.jdt.core.formatter.tabulation.char=space
4 |
5 | #Number of spaces used for indentation in case 'space' characters
6 | #have been selected. The default value is 4.
7 | org.eclipse.jdt.core.formatter.tabulation.size=2
8 |
9 | #Number of spaces used for indentation in case 'mixed' characters
10 | #have been selected. The default value is 4.
11 | org.eclipse.jdt.core.formatter.indentation.size=1
12 |
13 | #Whether or not indentation characters are inserted into empty lines.
14 | #The default value is 'true'.
15 | org.eclipse.jdt.core.formatter.indent_empty_lines=false
16 |
17 | #Number of spaces used for multiline indentation.
18 | #The default value is 2.
19 | groovy.formatter.multiline.indentation=1
20 |
21 | #Length after which list are considered too long. These will be wrapped.
22 | #The default value is 30.
23 | groovy.formatter.longListLength=30
24 |
25 | #Whether opening braces position shall be the next line.
26 | #The default value is 'same'.
27 | groovy.formatter.braces.start=same
28 |
29 | #Whether closing braces position shall be the next line.
30 | #The default value is 'next'.
31 | groovy.formatter.braces.end=next
32 |
33 | #Remove unnecessary semicolons. The default value is 'false'.
34 | groovy.formatter.remove.unnecessary.semicolons=false
35 |
36 | org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
37 | org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
38 | org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
39 | org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
40 | org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
41 | org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
42 | org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
43 | org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
44 | org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
45 | org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
46 | org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
47 | org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
48 | org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
49 | org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
50 |
51 | org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=insert
52 |
53 | # Formatter can be buggy in CI
54 | ignoreFormatterProblems=true
55 |
--------------------------------------------------------------------------------
/gradle/license-report-config/license-normalizer.json:
--------------------------------------------------------------------------------
1 | {
2 | "bundles" : [
3 | { "bundleName" : "MIT", "licenseName" : "MIT License", "licenseUrl" : "https://opensource.org/licenses/MIT" },
4 | { "bundleName" : "BSD", "licenseName" : "The BSD License", "licenseUrl" : "https://opensource.org/licenses/BSD-3-Clause" },
5 | { "bundleName" : "CDDL-1.1", "licenseName" : "COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.1", "licenseUrl" : "https://spdx.org/licenses/CDDL-1.1.html" },
6 | { "bundleName" : "Apache-2.0", "licenseName" : "Apache License, Version 2.0", "licenseUrl" : "https://www.apache.org/licenses/LICENSE-2.0" }
7 | ],
8 | "transformationRules" : [
9 | { "bundleName" : "MIT", "licenseNamePattern" : "\"MIT\\sLicense\"" },
10 | { "bundleName" : "BSD", "licenseNamePattern" : "BSD licence" },
11 | { "bundleName" : "CDDL-1.1", "licenseNamePattern" : "(.*)Dual license consisting of the CDDL v1.1 and GPL v2(.*)" },
12 | { "bundleName" : "Apache-2.0", "licenseNamePattern" : "(.*)Apache-2.0(.*)" }
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/gradle/owasp-suppression.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
11 | ^(?!pkg:maven/org\.json/json@).+$
12 | cpe:/a:json-java_project:json-java
13 |
14 |
15 |
22 | CVE-2020-8908
23 |
24 |
25 |
--------------------------------------------------------------------------------
/gradle/spotless.bash.license:
--------------------------------------------------------------------------------
1 | # Copyright $YEAR ConsenSys AG.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
4 | # the License. You may obtain a copy of the License at
5 | #
6 | # http://www.apache.org/licenses/LICENSE-2.0
7 | #
8 | # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
9 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
10 | # specific language governing permissions and limitations under the License.
11 |
12 |
--------------------------------------------------------------------------------
/gradle/spotless.java.license:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright $YEAR ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Consensys/signers/6bfdaf111f6c8590ce77221f0b9b682fe5c5e28d/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/keystorage/aws/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2022 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 |
14 | apply plugin: 'java-library'
15 | apply plugin: 'java-test-fixtures'
16 |
17 | jar {
18 | archiveBaseName = calculateJarName(project)
19 | manifest {
20 | attributes(
21 | 'Specification-Title': archiveBaseName.get(),
22 | 'Specification-Version': rootProject.version,
23 | 'Implementation-Title': archiveBaseName.get(),
24 | 'Implementation-Version': calculateVersion()
25 | )
26 | }
27 | }
28 |
29 | testFixturesJar {
30 | archiveBaseName = calculateJarName(project)
31 | }
32 |
33 | dependencies {
34 |
35 | implementation 'software.amazon.awssdk:auth'
36 | implementation 'software.amazon.awssdk:secretsmanager'
37 | implementation 'com.google.guava:guava'
38 | implementation 'org.apache.logging.log4j:log4j-api'
39 | implementation project(':keystorage:common')
40 | runtimeOnly 'software.amazon.awssdk:sts'
41 |
42 | testImplementation 'org.assertj:assertj-core'
43 | testImplementation 'org.junit.jupiter:junit-jupiter-engine'
44 | testImplementation 'org.junit.jupiter:junit-jupiter-api'
45 | testImplementation 'org.junit.jupiter:junit-jupiter-params'
46 |
47 | errorprone("com.google.errorprone:error_prone_core")
48 | }
49 |
--------------------------------------------------------------------------------
/keystorage/aws/src/main/java/tech/pegasys/signers/aws/AwsKeyIdentifier.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2022 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.aws;
14 |
15 | import java.util.Objects;
16 |
17 | import software.amazon.awssdk.regions.Region;
18 |
19 | public class AwsKeyIdentifier {
20 | private final String accessKeyId;
21 | private final Region region;
22 |
23 | public AwsKeyIdentifier(final String accessKeyId, final Region region) {
24 | this.accessKeyId = accessKeyId;
25 | this.region = region;
26 | }
27 |
28 | public String getAccessKeyId() {
29 | return accessKeyId;
30 | }
31 |
32 | public Region getRegion() {
33 | return region;
34 | }
35 |
36 | @Override
37 | public boolean equals(Object o) {
38 | if (this == o) return true;
39 | if (o == null || getClass() != o.getClass()) return false;
40 | AwsKeyIdentifier that = (AwsKeyIdentifier) o;
41 | return accessKeyId.equals(that.accessKeyId) && region.equals(that.region);
42 | }
43 |
44 | @Override
45 | public int hashCode() {
46 | return Objects.hash(accessKeyId, region);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/keystorage/aws/src/test/java/tech/pegasys/signers/aws/AwsSecret.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2022 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.aws;
14 |
15 | import java.util.Objects;
16 |
17 | public class AwsSecret {
18 | private final String secretValue;
19 | private final String tagKey;
20 | private final String tagValue;
21 |
22 | public AwsSecret(final String secretValue, final String tagKey, final String tagValue) {
23 | this.secretValue = secretValue;
24 | this.tagKey = tagKey;
25 | this.tagValue = tagValue;
26 | }
27 |
28 | public String getSecretValue() {
29 | return secretValue;
30 | }
31 |
32 | public String getTagKey() {
33 | return tagKey;
34 | }
35 |
36 | public String getTagValue() {
37 | return tagValue;
38 | }
39 |
40 | @Override
41 | public boolean equals(final Object o) {
42 | if (this == o) return true;
43 | if (o == null || getClass() != o.getClass()) return false;
44 | AwsSecret that = (AwsSecret) o;
45 | return secretValue.equals(that.secretValue)
46 | && tagKey.equals(that.tagKey)
47 | && tagValue.equals(that.tagValue);
48 | }
49 |
50 | @Override
51 | public int hashCode() {
52 | return Objects.hash(secretValue, tagKey, tagValue);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/keystorage/azure/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 |
14 | apply plugin: 'java-library'
15 | apply plugin: 'java-test-fixtures'
16 |
17 | jar {
18 | archiveBaseName = calculateJarName(project)
19 | manifest {
20 | attributes(
21 | 'Specification-Title': archiveBaseName.get(),
22 | 'Specification-Version': rootProject.version,
23 | 'Implementation-Title': archiveBaseName.get(),
24 | 'Implementation-Version': calculateVersion()
25 | )
26 | }
27 | }
28 |
29 | testFixturesJar {
30 | archiveBaseName = calculateJarName(project)
31 | }
32 |
33 | dependencies {
34 | implementation 'org.apache.logging.log4j:log4j-api'
35 | implementation 'com.azure:azure-security-keyvault-secrets'
36 | implementation 'com.azure:azure-security-keyvault-keys'
37 | implementation 'com.azure:azure-identity'
38 | implementation project(':keystorage:common')
39 |
40 | runtimeOnly 'org.apache.logging.log4j:log4j-core'
41 | runtimeOnly 'org.apache.logging.log4j:log4j-slf4j-impl'
42 |
43 | testImplementation 'org.assertj:assertj-core'
44 | testImplementation 'org.junit.jupiter:junit-jupiter-engine'
45 | testImplementation 'org.junit.jupiter:junit-jupiter-api'
46 | testImplementation 'org.junit.jupiter:junit-jupiter-params'
47 | testImplementation 'org.mockito:mockito-core'
48 |
49 | errorprone("com.google.errorprone:error_prone_core")
50 | }
51 |
--------------------------------------------------------------------------------
/keystorage/build.gradle:
--------------------------------------------------------------------------------
1 | jar { enabled = false }
2 |
--------------------------------------------------------------------------------
/keystorage/common/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 |
14 | apply plugin: 'java-library'
15 |
16 | jar {
17 | archiveBaseName = calculateJarName(project)
18 | manifest {
19 | attributes(
20 | 'Specification-Title': archiveBaseName.get(),
21 | 'Specification-Version': rootProject.version,
22 | 'Implementation-Title': archiveBaseName.get(),
23 | 'Implementation-Version': calculateVersion()
24 | )
25 | }
26 | }
27 |
28 | dependencies {
29 | implementation 'org.apache.logging.log4j:log4j-api'
30 | implementation 'com.google.guava:guava'
31 | runtimeOnly 'org.apache.logging.log4j:log4j-core'
32 | runtimeOnly 'org.apache.logging.log4j:log4j-slf4j-impl'
33 |
34 | testImplementation 'org.assertj:assertj-core'
35 | testImplementation 'de.neuland-bfi:assertj-logging-log4j'
36 | testImplementation 'org.junit.jupiter:junit-jupiter-engine'
37 | testImplementation 'org.junit.jupiter:junit-jupiter-api'
38 | testImplementation 'org.junit.jupiter:junit-jupiter-params'
39 |
40 | testRuntimeOnly 'org.apache.logging.log4j:log4j-core'
41 | testRuntimeOnly 'org.apache.logging.log4j:log4j-slf4j-impl'
42 | }
43 |
--------------------------------------------------------------------------------
/keystorage/common/src/main/java/tech/pegasys/signers/common/MappedResults.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.common;
14 |
15 | import java.util.Collection;
16 | import java.util.Collections;
17 | import java.util.HashSet;
18 | import java.util.List;
19 | import java.util.stream.Collectors;
20 | import java.util.stream.Stream;
21 |
22 | /** Contains Collection of Secret value result and count of errors. */
23 | public class MappedResults {
24 | private final Collection values;
25 | private int errorCount;
26 |
27 | MappedResults(final Collection values, final int errorCount) {
28 | this.values = values;
29 | this.errorCount = errorCount;
30 | }
31 |
32 | public static MappedResults errorResult() {
33 | return new MappedResults<>(Collections.emptyList(), 1);
34 | }
35 |
36 | public static MappedResults newSetInstance() {
37 | return new MappedResults<>(new HashSet<>(), 0);
38 | }
39 |
40 | public static MappedResults newInstance(final Collection values, final int errorCount) {
41 | return new MappedResults<>(values, errorCount);
42 | }
43 |
44 | public static MappedResults merge(
45 | final MappedResults first, final MappedResults second) {
46 | final List combinedList =
47 | Stream.concat(first.values.stream(), second.values.stream()).collect(Collectors.toList());
48 | final int errorCount = first.errorCount + second.errorCount;
49 | return new MappedResults<>(combinedList, errorCount);
50 | }
51 |
52 | public void mergeErrorCount(final int otherErrorCount) {
53 | this.errorCount += otherErrorCount;
54 | }
55 |
56 | public Collection getValues() {
57 | return values;
58 | }
59 |
60 | public int getErrorCount() {
61 | return errorCount;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/keystorage/common/src/main/java/tech/pegasys/signers/common/SecretValueMapperUtil.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.common;
14 |
15 | import java.util.Objects;
16 | import java.util.Set;
17 | import java.util.concurrent.atomic.AtomicInteger;
18 | import java.util.function.BiFunction;
19 | import java.util.stream.Collectors;
20 |
21 | import com.google.common.collect.Streams;
22 | import org.apache.logging.log4j.LogManager;
23 | import org.apache.logging.log4j.Logger;
24 |
25 | public class SecretValueMapperUtil {
26 | private static final Logger LOG = LogManager.getLogger();
27 |
28 | public static MappedResults mapSecretValue(
29 | BiFunction mapper, String secretName, String secretValue) {
30 | final AtomicInteger errorCount = new AtomicInteger(0);
31 | final Set result =
32 | Streams.mapWithIndex(
33 | secretValue.lines(),
34 | (value, index) -> {
35 | final R obj = mapper.apply(secretName, value);
36 | if (obj == null) {
37 | LOG.warn(
38 | "Value from secret name {} at index {} was not mapped and discarded.",
39 | secretName,
40 | index);
41 | errorCount.incrementAndGet();
42 | }
43 | return obj;
44 | })
45 | .filter(Objects::nonNull)
46 | .collect(Collectors.toSet());
47 | return MappedResults.newInstance(result, errorCount.intValue());
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/keystorage/hashicorp/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 |
14 | apply plugin: 'java-library'
15 | apply plugin: 'java-test-fixtures'
16 |
17 | jar {
18 | archiveBaseName = calculateJarName(project)
19 | manifest {
20 | attributes(
21 | 'Specification-Title': archiveBaseName.get(),
22 | 'Specification-Version': rootProject.version,
23 | 'Implementation-Title': archiveBaseName.get(),
24 | 'Implementation-Version': calculateVersion()
25 | )
26 | }
27 | }
28 |
29 | testFixturesJar {
30 | archiveBaseName = calculateJarName(project)
31 | }
32 |
33 | dependencies {
34 | implementation 'io.vertx:vertx-core'
35 | implementation 'org.apache.logging.log4j:log4j-api'
36 |
37 | implementation 'org.apache.tuweni:tuweni-toml'
38 | implementation 'org.apache.tuweni:tuweni-net'
39 | implementation 'org.bouncycastle:bcpkix-jdk15on'
40 | implementation 'org.bouncycastle:bcprov-jdk15on'
41 |
42 | runtimeOnly 'org.apache.logging.log4j:log4j-core'
43 | runtimeOnly 'org.apache.logging.log4j:log4j-slf4j-impl'
44 |
45 | testImplementation 'org.assertj:assertj-core'
46 | testImplementation 'org.junit.jupiter:junit-jupiter-engine'
47 | testImplementation 'org.junit.jupiter:junit-jupiter-api'
48 | testImplementation 'org.junit.jupiter:junit-jupiter-params'
49 | testImplementation 'org.mockito:mockito-core'
50 |
51 | integrationTestImplementation 'org.assertj:assertj-core'
52 | integrationTestImplementation 'org.junit.jupiter:junit-jupiter-api'
53 | integrationTestImplementation 'org.junit.jupiter:junit-jupiter-engine'
54 | integrationTestImplementation 'org.mock-server:mockserver-netty'
55 | integrationTestImplementation sourceSets.testFixtures.output
56 |
57 | errorprone("com.google.errorprone:error_prone_core")
58 |
59 | testFixturesImplementation 'org.apache.logging.log4j:log4j-api'
60 | testFixturesImplementation 'org.bouncycastle:bcpkix-jdk15on'
61 | testFixturesImplementation 'org.bouncycastle:bcprov-jdk15on'
62 | testFixturesImplementation 'com.fasterxml.jackson.core:jackson-databind'
63 | testFixturesImplementation 'org.assertj:assertj-core'
64 | testFixturesImplementation 'org.awaitility:awaitility'
65 | testFixturesImplementation 'org.apache.tuweni:tuweni-net'
66 | testFixturesImplementation 'org.zeroturnaround:zt-exec'
67 | }
68 |
--------------------------------------------------------------------------------
/keystorage/hashicorp/src/main/java/tech/pegasys/signers/hashicorp/HashicorpException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.hashicorp;
14 |
15 | public class HashicorpException extends RuntimeException {
16 |
17 | public HashicorpException() {}
18 |
19 | public HashicorpException(final String message) {
20 | super(message);
21 | }
22 |
23 | public HashicorpException(final String message, final Throwable cause) {
24 | super(message, cause);
25 | }
26 |
27 | public HashicorpException(final Throwable cause) {
28 | super(cause);
29 | }
30 |
31 | public HashicorpException(
32 | final String message,
33 | final Throwable cause,
34 | final boolean enableSuppression,
35 | final boolean writableStackTrace) {
36 | super(message, cause, enableSuppression, writableStackTrace);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/keystorage/hashicorp/src/main/java/tech/pegasys/signers/hashicorp/HashicorpKVResponseMapper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.hashicorp;
14 |
15 | import java.util.Collections;
16 | import java.util.Map;
17 | import java.util.Objects;
18 | import java.util.Optional;
19 | import java.util.stream.Collectors;
20 |
21 | import io.vertx.core.json.DecodeException;
22 | import io.vertx.core.json.JsonObject;
23 |
24 | public class HashicorpKVResponseMapper {
25 | public static final String ERROR_INVALID_JSON = "Invalid response returned from Hashicorp Vault";
26 |
27 | /**
28 | * Convert Hashicorp KV Version 2 Secret Engine JSON response to map of key/values
29 | *
30 | * @param json response from Hashicorp Vault
31 | * @return All key/value pairs
32 | */
33 | public static Map from(final String json) {
34 | if (json == null) {
35 | throw new HashicorpException(ERROR_INVALID_JSON);
36 | }
37 | final JsonObject jsonResponse;
38 | try {
39 | jsonResponse = new JsonObject(json);
40 | } catch (final DecodeException de) {
41 | throw new HashicorpException(ERROR_INVALID_JSON, de);
42 | }
43 |
44 | // expecting Hashicorp kv-v2 secret engine compatible JSON json
45 | final JsonObject keyData =
46 | Optional.ofNullable(jsonResponse.getJsonObject("data"))
47 | .map(jo -> jo.getJsonObject("data"))
48 | .orElseThrow(() -> new HashicorpException(ERROR_INVALID_JSON));
49 | return Collections.unmodifiableMap(
50 | keyData.stream()
51 | .filter(entry -> Objects.nonNull(entry.getValue()))
52 | .collect(
53 | Collectors.toMap(Map.Entry::getKey, HashicorpKVResponseMapper::getValueToString)));
54 | }
55 |
56 | private static String getValueToString(final Map.Entry v) {
57 | return v.getValue().toString();
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/keystorage/hashicorp/src/main/java/tech/pegasys/signers/hashicorp/TrustStoreType.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.hashicorp;
14 |
15 | import java.util.EnumSet;
16 | import java.util.Optional;
17 |
18 | public enum TrustStoreType {
19 | JKS(true),
20 | PKCS12(true),
21 | WHITELIST(false),
22 | ALLOWLIST(false),
23 | PEM(false);
24 |
25 | private boolean passwordRequired;
26 |
27 | TrustStoreType(final boolean passwordRequired) {
28 | this.passwordRequired = passwordRequired;
29 | }
30 |
31 | public boolean isPasswordRequired() {
32 | return passwordRequired;
33 | }
34 |
35 | public static Optional fromString(final String tsType) {
36 | return EnumSet.allOf(TrustStoreType.class).stream()
37 | .filter(t -> t.name().equals(tsType))
38 | .findAny();
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/keystorage/hashicorp/src/main/java/tech/pegasys/signers/hashicorp/config/ConnectionParameters.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.hashicorp.config;
14 |
15 | import java.net.URI;
16 | import java.util.Optional;
17 |
18 | public class ConnectionParameters {
19 | private static final Long DEFAULT_TIMEOUT_MILLISECONDS = 10_000L;
20 | private static final Integer DEFAULT_SERVER_PORT = 8200;
21 | private final String serverHost;
22 | private final int serverPort;
23 | private final Optional tlsOptions;
24 | private final long timeoutMs;
25 |
26 | private final URI vaultURI;
27 |
28 | /* Optional parameters will be set to their defaults when connecting */
29 | public ConnectionParameters(
30 | final String serverHost,
31 | final Optional serverPort,
32 | final Optional tlsOptions,
33 | final Optional timeoutMs) {
34 | this.serverHost = serverHost;
35 | this.serverPort = serverPort.orElse(DEFAULT_SERVER_PORT);
36 | this.tlsOptions = tlsOptions;
37 | this.timeoutMs = timeoutMs.orElse(DEFAULT_TIMEOUT_MILLISECONDS);
38 | final String scheme = tlsOptions.isPresent() ? "https" : "http";
39 | this.vaultURI = URI.create(String.format("%s://%s:%d", scheme, serverHost, this.serverPort));
40 | }
41 |
42 | public String getServerHost() {
43 | return serverHost;
44 | }
45 |
46 | public int getServerPort() {
47 | return serverPort;
48 | }
49 |
50 | public Optional getTlsOptions() {
51 | return tlsOptions;
52 | }
53 |
54 | public long getTimeoutMilliseconds() {
55 | return timeoutMs;
56 | }
57 |
58 | public URI getVaultURI() {
59 | return vaultURI;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/keystorage/hashicorp/src/main/java/tech/pegasys/signers/hashicorp/config/HashicorpKeyConfig.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.hashicorp.config;
14 |
15 | public class HashicorpKeyConfig {
16 |
17 | private final ConnectionParameters connectionParams;
18 | private final KeyDefinition keyDefinition;
19 |
20 | public HashicorpKeyConfig(
21 | final ConnectionParameters connectionParams, final KeyDefinition keyDefinition) {
22 | this.connectionParams = connectionParams;
23 | this.keyDefinition = keyDefinition;
24 | }
25 |
26 | public ConnectionParameters getConnectionParams() {
27 | return connectionParams;
28 | }
29 |
30 | public KeyDefinition getKeyDefinition() {
31 | return keyDefinition;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/keystorage/hashicorp/src/main/java/tech/pegasys/signers/hashicorp/config/KeyDefinition.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.hashicorp.config;
14 |
15 | import java.util.Optional;
16 |
17 | public class KeyDefinition {
18 |
19 | private String keyPath;
20 | private Optional keyName;
21 | private String token;
22 |
23 | public KeyDefinition(final String keyPath, final Optional keyName, final String token) {
24 | this.keyPath = keyPath;
25 | this.keyName = keyName;
26 | this.token = token;
27 | }
28 |
29 | public String getKeyPath() {
30 | return keyPath;
31 | }
32 |
33 | public Optional getKeyName() {
34 | return keyName;
35 | }
36 |
37 | public String getToken() {
38 | return token;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/keystorage/hashicorp/src/main/java/tech/pegasys/signers/hashicorp/config/TlsOptions.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.hashicorp.config;
14 |
15 | import tech.pegasys.signers.hashicorp.TrustStoreType;
16 |
17 | import java.nio.file.Path;
18 | import java.util.Optional;
19 |
20 | public class TlsOptions {
21 |
22 | private final Optional trustStoreType;
23 | private final Path trustStorePath;
24 | private final String trustStorePassword;
25 |
26 | public TlsOptions(
27 | final Optional trustStoreType,
28 | final Path trustStorePath,
29 | final String trustStorePassword) {
30 | this.trustStoreType = trustStoreType;
31 | this.trustStorePath = trustStorePath;
32 | this.trustStorePassword = trustStorePassword;
33 | }
34 |
35 | public Optional getTrustStoreType() {
36 | return trustStoreType;
37 | }
38 |
39 | public Path getTrustStorePath() {
40 | return trustStorePath;
41 | }
42 |
43 | public String getTrustStorePassword() {
44 | return trustStorePassword;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/keystorage/hashicorp/src/main/java/tech/pegasys/signers/hashicorp/config/loader/toml/TomlParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.hashicorp.config.loader.toml;
14 |
15 | import tech.pegasys.signers.hashicorp.HashicorpException;
16 |
17 | import java.io.IOException;
18 | import java.nio.charset.StandardCharsets;
19 | import java.nio.file.Files;
20 | import java.nio.file.Path;
21 | import java.util.stream.Collectors;
22 |
23 | import org.apache.logging.log4j.LogManager;
24 | import org.apache.logging.log4j.Logger;
25 | import org.apache.tuweni.toml.Toml;
26 | import org.apache.tuweni.toml.TomlParseError;
27 | import org.apache.tuweni.toml.TomlParseResult;
28 |
29 | public class TomlParser {
30 | private static final Logger LOG = LogManager.getLogger();
31 |
32 | public TomlParseResult getTomlParseResult(final Path tomlConfigurationFile) {
33 | try {
34 | return getTomlParseResult(Files.readString(tomlConfigurationFile, StandardCharsets.UTF_8));
35 | } catch (final IOException e) {
36 | throw new HashicorpException("Error reading Hashicorp configuration file", e);
37 | }
38 | }
39 |
40 | public TomlParseResult getTomlParseResult(final String tomlConfiguration) {
41 | final TomlParseResult tomlParseResult = Toml.parse(tomlConfiguration);
42 | if (tomlParseResult.hasErrors()) {
43 | LOG.debug(() -> joinErrors(tomlParseResult));
44 | throw new HashicorpException("Error parsing Hashicorp configuration");
45 | }
46 | return tomlParseResult;
47 | }
48 |
49 | private String joinErrors(final TomlParseResult result) {
50 | return result.errors().stream()
51 | .map(TomlParseError::toString)
52 | .collect(Collectors.joining(System.lineSeparator()));
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/keystorage/hashicorp/src/test/java/tech/pegasys/signers/hashicorp/HashicorpConnectionTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.hashicorp;
14 |
15 | import static org.assertj.core.api.Assertions.assertThatThrownBy;
16 |
17 | import tech.pegasys.signers.hashicorp.config.ConnectionParameters;
18 | import tech.pegasys.signers.hashicorp.config.TlsOptions;
19 |
20 | import java.io.EOFException;
21 | import java.io.File;
22 | import java.io.IOException;
23 | import java.net.URL;
24 | import java.nio.file.Path;
25 | import java.util.Optional;
26 |
27 | import com.google.common.io.Resources;
28 | import org.junit.jupiter.api.Test;
29 |
30 | public class HashicorpConnectionTest {
31 |
32 | private static final String CONFIGURED_HOST = "Host";
33 | private final HashicorpConnectionFactory connectionFactory = new HashicorpConnectionFactory();
34 |
35 | @Test
36 | void missingJksTrustStoreFileThrowsHashicorpException() throws IOException {
37 |
38 | final File tempFile = File.createTempFile("trustStore", ".tmp");
39 | tempFile.deleteOnExit();
40 | final TlsOptions tlsOptions =
41 | new TlsOptions(Optional.of(TrustStoreType.JKS), tempFile.toPath(), "anyPassword");
42 |
43 | final ConnectionParameters params =
44 | new ConnectionParameters(
45 | CONFIGURED_HOST, Optional.empty(), Optional.of(tlsOptions), Optional.of(10L));
46 |
47 | assertThatThrownBy(() -> connectionFactory.create(params))
48 | .isInstanceOf(HashicorpException.class)
49 | .hasMessage("Unable to initialise connection to hashicorp vault.")
50 | .getCause()
51 | .isInstanceOf(EOFException.class);
52 | }
53 |
54 | @Test
55 | void pkcs12FileWithIncorrectPasswordThrowsHashicorpException() {
56 |
57 | final URL sslCertificate = Resources.getResource("tls/cert1.pfx");
58 | final Path keystorePath = Path.of(sslCertificate.getPath());
59 |
60 | // valid password is "password"
61 | final TlsOptions tlsOptions =
62 | new TlsOptions(Optional.of(TrustStoreType.PKCS12), keystorePath, "wrongPassword");
63 |
64 | final ConnectionParameters params =
65 | new ConnectionParameters(
66 | CONFIGURED_HOST, Optional.empty(), Optional.of(tlsOptions), Optional.of(10L));
67 |
68 | assertThatThrownBy(() -> connectionFactory.create(params))
69 | .isInstanceOf(HashicorpException.class)
70 | .hasMessage("Unable to initialise connection to hashicorp vault.")
71 | .getCause()
72 | .isInstanceOf(IOException.class)
73 | .hasMessage("keystore password was incorrect");
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/keystorage/hashicorp/src/test/java/tech/pegasys/signers/hashicorp/HashicorpKVResponseMapperTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.hashicorp;
14 |
15 | import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
16 |
17 | import java.util.Map;
18 |
19 | import org.assertj.core.api.Assertions;
20 | import org.junit.jupiter.api.Test;
21 |
22 | class HashicorpKVResponseMapperTest {
23 |
24 | private static final String VALID_JSON_RESPONSE =
25 | "{\n"
26 | + " \"request_id\": \"39ae72e7-ef58-ab8b-9aef-4473a4ea2c46\",\n"
27 | + " \"lease_id\": \"\",\n"
28 | + " \"renewable\": false,\n"
29 | + " \"lease_duration\": 0,\n"
30 | + " \"data\": {\n"
31 | + " \"data\": {\n"
32 | + " \"dbKey1\": \"1c2c450cedaa416329fef5900854d55c00046224dffd0075b5057a088b48f9bf\",\n"
33 | + " \"value\": \"ccccaaacedaa416329fef5900854d55c00046224dffd0075b5057a088b48f9bf\"\n"
34 | + " },\n"
35 | + " \"metadata\": {\n"
36 | + " \"created_time\": \"2019-11-06T08:21:41.656367376Z\",\n"
37 | + " \"deletion_time\": \"\",\n"
38 | + " \"destroyed\": false,\n"
39 | + " \"version\": 1\n"
40 | + " }\n"
41 | + " },\n"
42 | + " \"wrap_info\": null,\n"
43 | + " \"warnings\": null,\n"
44 | + " \"auth\": null\n"
45 | + "}";
46 |
47 | @Test
48 | void exceptionThrownWhenParsingNullJsonInput() {
49 | assertThatThrownBy(() -> HashicorpKVResponseMapper.from(null))
50 | .isInstanceOf(HashicorpException.class)
51 | .hasMessage(HashicorpKVResponseMapper.ERROR_INVALID_JSON);
52 | }
53 |
54 | @Test
55 | void exceptionThrownWhenParsingInvalidJsonInput() {
56 | assertThatThrownBy(() -> HashicorpKVResponseMapper.from("invalidjson{"))
57 | .isInstanceOf(HashicorpException.class)
58 | .hasMessage(HashicorpKVResponseMapper.ERROR_INVALID_JSON);
59 | }
60 |
61 | @Test
62 | void exceptionThrownWhenParsingUnexpectedJsonInput() {
63 | assertThatThrownBy(() -> HashicorpKVResponseMapper.from("{\"test\":\"value\"}"))
64 | .isInstanceOf(HashicorpException.class)
65 | .hasMessage(HashicorpKVResponseMapper.ERROR_INVALID_JSON);
66 | }
67 |
68 | @Test
69 | void mapReturnedFromValidJsonResponse() {
70 | final Map kvMap = HashicorpKVResponseMapper.from(VALID_JSON_RESPONSE);
71 | Assertions.assertThat(kvMap).containsOnlyKeys("value", "dbKey1").isNotNull();
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/keystorage/hashicorp/src/test/java/tech/pegasys/signers/hashicorp/TrustStoreTypeTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.hashicorp;
14 |
15 | import static org.junit.jupiter.api.Assertions.assertEquals;
16 |
17 | import java.util.Optional;
18 |
19 | import org.junit.jupiter.api.Test;
20 |
21 | class TrustStoreTypeTest {
22 |
23 | @Test
24 | void trustStoreTypeCreatedFromValidValue() {
25 | assertEquals(Optional.of(TrustStoreType.PEM), TrustStoreType.fromString("PEM"));
26 | }
27 |
28 | @Test
29 | void turstStoreTypeEmptyFromInvalidValue() {
30 | assertEquals(Optional.empty(), TrustStoreType.fromString("X"));
31 | assertEquals(Optional.empty(), TrustStoreType.fromString("pem"));
32 | assertEquals(Optional.empty(), TrustStoreType.fromString(null));
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/keystorage/hashicorp/src/test/resources/tls/cert1.pfx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Consensys/signers/6bfdaf111f6c8590ce77221f0b9b682fe5c5e28d/keystorage/hashicorp/src/test/resources/tls/cert1.pfx
--------------------------------------------------------------------------------
/keystorage/hashicorp/src/testFixtures/java/tech/pegasys/signers/hashicorp/dsl/HashicorpVaultCommands.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.hashicorp.dsl;
14 |
15 | public class HashicorpVaultCommands {
16 |
17 | private final String vaultCommand;
18 | private final String vaultUrl;
19 |
20 | public HashicorpVaultCommands(final String vaultCommand, final String vaultUrl) {
21 | this.vaultCommand = vaultCommand;
22 | this.vaultUrl = vaultUrl;
23 | }
24 |
25 | public String[] initCommand() {
26 | return new String[] {
27 | vaultCommand,
28 | "operator",
29 | "init",
30 | "-key-shares=1",
31 | "-key-threshold=1",
32 | "-format=json",
33 | "-address=" + vaultUrl
34 | };
35 | }
36 |
37 | public String[] enableSecretEngineCommand(final String vaultRootPath) {
38 | return new String[] {
39 | vaultCommand, "secrets", "enable", "-address=" + vaultUrl, "-path=" + vaultRootPath, "kv-v2",
40 | };
41 | }
42 |
43 | public String[] unseal(final String unsealKey) {
44 | return new String[] {
45 | vaultCommand, "operator", "unseal", "-address=" + vaultUrl, "-format=json", unsealKey
46 | };
47 | }
48 |
49 | public String[] putSecretCommand(final String key, final String value, final String path) {
50 | final String paramString = String.format("%s=%s", key, value);
51 | return new String[] {
52 | vaultCommand, "kv", "put", "-address=" + vaultUrl, path, paramString,
53 | };
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/keystorage/hashicorp/src/testFixtures/java/tech/pegasys/signers/hashicorp/dsl/HashicorpVaultTokens.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.hashicorp.dsl;
14 |
15 | public class HashicorpVaultTokens {
16 | private final String unsealKey;
17 | private final String rootToken;
18 |
19 | public HashicorpVaultTokens(final String unsealKey, final String rootToken) {
20 | this.unsealKey = unsealKey;
21 | this.rootToken = rootToken;
22 | }
23 |
24 | public String getUnsealKey() {
25 | return unsealKey;
26 | }
27 |
28 | public String getRootToken() {
29 | return rootToken;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/keystorage/interlock/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 |
14 | apply plugin: 'java-library'
15 |
16 | jar {
17 | archiveBaseName = calculateJarName(project)
18 | manifest {
19 | attributes(
20 | 'Specification-Title': archiveBaseName.get(),
21 | 'Specification-Version': rootProject.version,
22 | 'Implementation-Title': archiveBaseName.get(),
23 | 'Implementation-Version': calculateVersion()
24 | )
25 | }
26 | }
27 |
28 | dependencies {
29 | implementation 'io.vertx:vertx-core'
30 | implementation 'org.apache.logging.log4j:log4j-api'
31 |
32 | implementation 'org.apache.tuweni:tuweni-toml'
33 | implementation 'org.apache.tuweni:tuweni-net'
34 | implementation 'org.apache.commons:commons-lang3'
35 | implementation 'commons-io:commons-io'
36 |
37 | runtimeOnly 'org.apache.logging.log4j:log4j-core'
38 | runtimeOnly 'org.apache.logging.log4j:log4j-slf4j-impl'
39 | runtimeOnly 'org.bouncycastle:bcpkix-jdk15on'
40 | runtimeOnly 'org.bouncycastle:bcprov-jdk15on'
41 |
42 | testImplementation 'org.assertj:assertj-core'
43 | testImplementation 'org.junit.jupiter:junit-jupiter-engine'
44 | testImplementation 'org.junit.jupiter:junit-jupiter-api'
45 | testImplementation 'org.junit.jupiter:junit-jupiter-params'
46 | testImplementation 'org.mockito:mockito-core'
47 |
48 | testRuntimeOnly 'org.bouncycastle:bcpkix-jdk15on'
49 | testRuntimeOnly 'org.bouncycastle:bcprov-jdk15on'
50 | testRuntimeOnly 'org.apache.logging.log4j:log4j-core'
51 | testRuntimeOnly 'org.apache.logging.log4j:log4j-slf4j-impl'
52 | testRuntimeOnly 'org.apache.logging.log4j:log4j-api'
53 | }
54 |
--------------------------------------------------------------------------------
/keystorage/interlock/src/main/java/tech/pegasys/signers/interlock/InterlockClientException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.interlock;
14 |
15 | public class InterlockClientException extends RuntimeException {
16 | public InterlockClientException(final String message) {
17 | super(message);
18 | }
19 |
20 | public InterlockClientException(final String message, final Throwable cause) {
21 | super(message, cause);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/keystorage/interlock/src/main/java/tech/pegasys/signers/interlock/InterlockSession.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.interlock;
14 |
15 | import org.apache.tuweni.bytes.Bytes;
16 |
17 | public interface InterlockSession extends AutoCloseable {
18 |
19 | /**
20 | * Fetch key from given path. It is expected that the private key is stored in hex format in given
21 | * file.
22 | *
23 | * @param keyPath The path of key file in Interlock, for instance "/bls/key1.txt"
24 | * @return org.apache.tuweni.bytes.Bytes representing raw private key.
25 | * @throws InterlockClientException In case of an error while fetching key
26 | */
27 | Bytes fetchKey(String keyPath) throws InterlockClientException;
28 |
29 | /** Logout from Interlock Session */
30 | @Override
31 | void close();
32 | }
33 |
--------------------------------------------------------------------------------
/keystorage/interlock/src/main/java/tech/pegasys/signers/interlock/InterlockSessionFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.interlock;
14 |
15 | import java.net.URI;
16 |
17 | public interface InterlockSessionFactory {
18 | InterlockSession newSession(URI interlockURI, String volume, String password);
19 | }
20 |
--------------------------------------------------------------------------------
/keystorage/interlock/src/main/java/tech/pegasys/signers/interlock/InterlockSessionFactoryProvider.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.interlock;
14 |
15 | import tech.pegasys.signers.interlock.vertx.InterlockSessionFactoryImpl;
16 |
17 | import java.nio.file.Path;
18 | import java.time.Duration;
19 |
20 | import io.vertx.core.Vertx;
21 | import org.apache.commons.lang3.StringUtils;
22 |
23 | public class InterlockSessionFactoryProvider {
24 | private static final String HTTP_CLIENT_TIMEOUT_ENV = "INTERLOCK_CLIENT_TIMEOUT_MS";
25 | private static final int DEFAULT_TIMEOUT_MS = 5000;
26 | private static final Duration HTTP_CLIENT_TIMEOUT_DURATION = timeoutDuration();
27 |
28 | public static InterlockSessionFactoryImpl newInstance(
29 | final Vertx vertx, final Path knownServersFile) {
30 | return new InterlockSessionFactoryImpl(vertx, knownServersFile, HTTP_CLIENT_TIMEOUT_DURATION);
31 | }
32 |
33 | private static Duration timeoutDuration() {
34 | final String timeoutStr = System.getenv(HTTP_CLIENT_TIMEOUT_ENV);
35 | if (StringUtils.isBlank(timeoutStr)) {
36 | return Duration.ofMillis(DEFAULT_TIMEOUT_MS);
37 | }
38 |
39 | try {
40 | final int timeout = Integer.parseInt(timeoutStr);
41 | if (timeout < 0) {
42 | throw new NumberFormatException();
43 | }
44 | return Duration.ofMillis(timeout);
45 | } catch (final NumberFormatException e) {
46 | throw new IllegalArgumentException("Invalid Interlock client timeout " + timeoutStr);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/keystorage/interlock/src/main/java/tech/pegasys/signers/interlock/model/ApiAuth.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.interlock.model;
14 |
15 | import java.util.List;
16 |
17 | public class ApiAuth {
18 | public static final String XSRF_TOKEN_HEADER = "X-XSRFToken";
19 | private final String token;
20 | private final List cookies;
21 |
22 | public ApiAuth(final String token, final List cookies) {
23 | this.token = token;
24 | this.cookies = cookies;
25 | }
26 |
27 | public List getCookies() {
28 | return cookies;
29 | }
30 |
31 | public String getToken() {
32 | return token;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/keystorage/interlock/src/main/java/tech/pegasys/signers/interlock/vertx/InterlockSessionImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.interlock.vertx;
14 |
15 | import tech.pegasys.signers.interlock.InterlockClientException;
16 | import tech.pegasys.signers.interlock.InterlockSession;
17 | import tech.pegasys.signers.interlock.model.ApiAuth;
18 | import tech.pegasys.signers.interlock.vertx.operations.FileDownloadIdOperation;
19 | import tech.pegasys.signers.interlock.vertx.operations.FileDownloadOperation;
20 | import tech.pegasys.signers.interlock.vertx.operations.LogoutOperation;
21 |
22 | import io.vertx.core.http.HttpClient;
23 | import org.apache.logging.log4j.LogManager;
24 | import org.apache.logging.log4j.Logger;
25 | import org.apache.tuweni.bytes.Bytes;
26 |
27 | public class InterlockSessionImpl implements InterlockSession {
28 | private static final Logger LOG = LogManager.getLogger();
29 |
30 | private final ApiAuth apiAuth;
31 | private final HttpClient httpClient;
32 |
33 | public InterlockSessionImpl(final HttpClient httpClient, final ApiAuth apiAuth) {
34 | this.httpClient = httpClient;
35 | this.apiAuth = apiAuth;
36 | }
37 |
38 | @Override
39 | public Bytes fetchKey(final String keyPath) throws InterlockClientException {
40 | LOG.trace("Fetching key from {}.", keyPath);
41 | try {
42 | final String downloadId =
43 | new FileDownloadIdOperation(httpClient, apiAuth, keyPath).waitForResponse();
44 | final String keyStr =
45 | new FileDownloadOperation(httpClient, apiAuth, downloadId).waitForResponse();
46 | return Bytes.fromHexString(keyStr);
47 | } catch (final InterlockClientException e) {
48 | LOG.warn("Downloading {} failed due to: {}", keyPath, e.getMessage());
49 | throw new InterlockClientException("Unable to download " + keyPath);
50 | } catch (final IllegalArgumentException e) {
51 | LOG.warn(
52 | "Downloaded content from {} failed to convert to Bytes: {}", keyPath, e.getMessage());
53 | throw new InterlockClientException("Invalid content received from " + keyPath);
54 | }
55 | }
56 |
57 | @Override
58 | public void close() {
59 | LOG.trace("Closing session");
60 | try {
61 | new LogoutOperation(httpClient, apiAuth).waitForResponse();
62 | } catch (final RuntimeException e) {
63 | LOG.warn("Interlock Session Logout operation failed: " + e.getMessage());
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/keystorage/interlock/src/main/java/tech/pegasys/signers/interlock/vertx/operations/ApiOperation.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.interlock.vertx.operations;
14 |
15 | import tech.pegasys.signers.interlock.InterlockClientException;
16 |
17 | public interface ApiOperation {
18 | T waitForResponse() throws InterlockClientException;
19 | }
20 |
--------------------------------------------------------------------------------
/keystorage/interlock/src/main/java/tech/pegasys/signers/interlock/vertx/operations/FileDownloadIdOperation.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.interlock.vertx.operations;
14 |
15 | import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE;
16 | import static io.vertx.core.http.HttpHeaders.COOKIE;
17 | import static io.vertx.core.http.HttpMethod.POST;
18 | import static tech.pegasys.signers.interlock.model.ApiAuth.XSRF_TOKEN_HEADER;
19 |
20 | import tech.pegasys.signers.interlock.model.ApiAuth;
21 |
22 | import io.vertx.core.MultiMap;
23 | import io.vertx.core.http.HttpClient;
24 | import io.vertx.core.json.JsonObject;
25 |
26 | public class FileDownloadIdOperation extends AbstractOperation {
27 | private final HttpClient httpClient;
28 | private final ApiAuth apiAuth;
29 | private final String keyPath;
30 |
31 | public FileDownloadIdOperation(
32 | final HttpClient httpClient, final ApiAuth apiAuth, final String keyPath) {
33 | this.httpClient = httpClient;
34 | this.apiAuth = apiAuth;
35 | this.keyPath = keyPath;
36 | }
37 |
38 | @Override
39 | protected void invoke() {
40 | final String body = new JsonObject().put("path", keyPath).encode();
41 | httpClient
42 | .request(POST, "/api/file/download")
43 | .onSuccess(
44 | request -> {
45 | request.response().onSuccess(this::handle).onFailure(this::handleException);
46 | request.exceptionHandler(this::handleException);
47 | request.putHeader(CONTENT_TYPE, "application/json");
48 | request.putHeader(XSRF_TOKEN_HEADER, apiAuth.getToken());
49 | request.putHeader(COOKIE.toString(), apiAuth.getCookies());
50 | request.end(body);
51 | })
52 | .onFailure(this::handleException);
53 | }
54 |
55 | @Override
56 | protected String processJsonResponse(final JsonObject json, final MultiMap headers) {
57 | return json.getString("response");
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/keystorage/interlock/src/main/java/tech/pegasys/signers/interlock/vertx/operations/FileDownloadOperation.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.interlock.vertx.operations;
14 |
15 | import static io.vertx.core.http.HttpHeaders.COOKIE;
16 | import static io.vertx.core.http.HttpMethod.GET;
17 |
18 | import tech.pegasys.signers.interlock.model.ApiAuth;
19 |
20 | import java.net.URLEncoder;
21 | import java.nio.charset.StandardCharsets;
22 |
23 | import io.vertx.core.buffer.Buffer;
24 | import io.vertx.core.http.HttpClient;
25 | import io.vertx.core.http.HttpClientResponse;
26 |
27 | public class FileDownloadOperation extends AbstractOperation {
28 | private final HttpClient httpClient;
29 | private final ApiAuth apiAuth;
30 | private final String downloadId;
31 |
32 | public FileDownloadOperation(
33 | final HttpClient httpClient, final ApiAuth apiAuth, final String downloadId) {
34 | this.httpClient = httpClient;
35 | this.apiAuth = apiAuth;
36 | this.downloadId = downloadId;
37 | }
38 |
39 | @Override
40 | protected void invoke() {
41 | httpClient
42 | .request(GET, "/api/file/download?" + downloadIdQueryParam(downloadId))
43 | .onSuccess(
44 | request -> {
45 | request.response().onSuccess(this::handle).onFailure(this::handleException);
46 | request.exceptionHandler(this::handleException);
47 | request.putHeader(COOKIE.toString(), apiAuth.getCookies());
48 | request.end();
49 | })
50 | .onFailure(this::handleException);
51 | }
52 |
53 | @Override
54 | protected void handleResponseBuffer(final HttpClientResponse response, final Buffer buffer) {
55 | getResponseFuture().complete(buffer.toString(StandardCharsets.UTF_8));
56 | }
57 |
58 | private String downloadIdQueryParam(final String downloadId) {
59 | return "id=" + URLEncoder.encode(downloadId, StandardCharsets.UTF_8);
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/keystorage/interlock/src/main/java/tech/pegasys/signers/interlock/vertx/operations/LoginOperation.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.interlock.vertx.operations;
14 |
15 | import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE;
16 | import static io.vertx.core.http.HttpMethod.POST;
17 |
18 | import tech.pegasys.signers.interlock.model.ApiAuth;
19 |
20 | import java.util.List;
21 |
22 | import io.vertx.core.MultiMap;
23 | import io.vertx.core.http.HttpClient;
24 | import io.vertx.core.http.HttpHeaders;
25 | import io.vertx.core.json.JsonObject;
26 |
27 | public class LoginOperation extends AbstractOperation {
28 | private final HttpClient httpClient;
29 | private final String volume;
30 | private final String password;
31 |
32 | public LoginOperation(final HttpClient httpClient, final String volume, final String password) {
33 | this.httpClient = httpClient;
34 | this.volume = volume;
35 | this.password = password;
36 | }
37 |
38 | @Override
39 | protected void invoke() {
40 | final String body =
41 | new JsonObject()
42 | .put("volume", volume)
43 | .put("password", password)
44 | .put("dispose", false)
45 | .encode();
46 | httpClient
47 | .request(POST, "/api/auth/login")
48 | .onSuccess(
49 | request -> {
50 | request.response().onSuccess(this::handle).onFailure(this::handleException);
51 | request.exceptionHandler(this::handleException);
52 | request.putHeader(CONTENT_TYPE, "application/json");
53 | request.end(body);
54 | })
55 | .onFailure(this::handleException);
56 | }
57 |
58 | @Override
59 | protected ApiAuth processJsonResponse(final JsonObject json, final MultiMap headers) {
60 | final String xsrfToken = json.getJsonObject("response").getString("XSRFToken");
61 | final List cookies = headers.getAll(HttpHeaders.SET_COOKIE);
62 | return new ApiAuth(xsrfToken, cookies);
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/keystorage/interlock/src/main/java/tech/pegasys/signers/interlock/vertx/operations/LogoutOperation.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.interlock.vertx.operations;
14 |
15 | import static io.vertx.core.http.HttpHeaders.COOKIE;
16 | import static io.vertx.core.http.HttpMethod.POST;
17 | import static tech.pegasys.signers.interlock.model.ApiAuth.XSRF_TOKEN_HEADER;
18 |
19 | import tech.pegasys.signers.interlock.model.ApiAuth;
20 |
21 | import io.vertx.core.http.HttpClient;
22 |
23 | public class LogoutOperation extends AbstractOperation {
24 | private final HttpClient httpClient;
25 | private final ApiAuth apiAuth;
26 |
27 | public LogoutOperation(final HttpClient httpClient, final ApiAuth apiAuth) {
28 | this.httpClient = httpClient;
29 | this.apiAuth = apiAuth;
30 | }
31 |
32 | @Override
33 | protected void invoke() {
34 | httpClient
35 | .request(POST, "/api/auth/logout")
36 | .onSuccess(
37 | request -> {
38 | request.response().onSuccess(this::handle).onFailure(this::handleException);
39 | request.exceptionHandler(this::handleException);
40 | request.putHeader(XSRF_TOKEN_HEADER, apiAuth.getToken());
41 | request.putHeader(COOKIE.toString(), apiAuth.getCookies());
42 | request.end();
43 | })
44 | .onFailure(this::handleException);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/keystorage/interlock/src/test/resources/log4j2-test.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/keystorage/yubihsm2/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 |
14 | apply plugin: 'java-library'
15 |
16 | jar {
17 | archiveBaseName = calculateJarName(project)
18 | manifest {
19 | attributes(
20 | 'Specification-Title': archiveBaseName.get(),
21 | 'Specification-Version': rootProject.version,
22 | 'Implementation-Title': archiveBaseName.get(),
23 | 'Implementation-Version': calculateVersion()
24 | )
25 | }
26 | }
27 |
28 | dependencies {
29 | implementation 'org.apache.logging.log4j:log4j-api'
30 | implementation 'org.apache.tuweni:tuweni-bytes'
31 | implementation 'org.xipki.iaik:sunpkcs11-wrapper'
32 |
33 | runtimeOnly 'org.apache.logging.log4j:log4j-core'
34 | runtimeOnly 'org.apache.logging.log4j:log4j-slf4j-impl'
35 |
36 | testImplementation 'org.assertj:assertj-core'
37 | testImplementation 'org.junit.jupiter:junit-jupiter-engine'
38 | testImplementation 'org.junit.jupiter:junit-jupiter-api'
39 | testImplementation 'org.junit.jupiter:junit-jupiter-params'
40 |
41 | errorprone("com.google.errorprone:error_prone_core")
42 | }
43 |
--------------------------------------------------------------------------------
/keystorage/yubihsm2/src/main/java/tech/pegasys/signers/yubihsm/YubiHsm.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.yubihsm;
14 |
15 | import org.apache.tuweni.bytes.Bytes;
16 |
17 | public interface YubiHsm {
18 |
19 | /**
20 | * Fetch key as opaque data from YubiHSM
21 | *
22 | * @param opaqueObjId Opaque object id
23 | * @return data as Bytes
24 | * @throws YubiHsmException if unable to fetch data
25 | */
26 | Bytes fetchOpaqueData(short opaqueObjId) throws YubiHsmException;
27 | }
28 |
--------------------------------------------------------------------------------
/keystorage/yubihsm2/src/main/java/tech/pegasys/signers/yubihsm/YubiHsmException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.yubihsm;
14 |
15 | public class YubiHsmException extends RuntimeException {
16 | public YubiHsmException() {
17 | super();
18 | }
19 |
20 | public YubiHsmException(final String message) {
21 | super(message);
22 | }
23 |
24 | public YubiHsmException(final String message, final Throwable cause) {
25 | super(message, cause);
26 | }
27 |
28 | public YubiHsmException(final Throwable cause) {
29 | super(cause);
30 | }
31 |
32 | protected YubiHsmException(
33 | final String message,
34 | final Throwable cause,
35 | final boolean enableSuppression,
36 | final boolean writableStackTrace) {
37 | super(message, cause, enableSuppression, writableStackTrace);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/keystorage/yubihsm2/src/main/java/tech/pegasys/signers/yubihsm/pkcs11/ExtendedData.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.yubihsm.pkcs11;
14 |
15 | import iaik.pkcs.pkcs11.objects.Attribute;
16 | import iaik.pkcs.pkcs11.objects.ByteArrayAttribute;
17 | import iaik.pkcs.pkcs11.objects.Data;
18 | import org.apache.tuweni.bytes.Bytes;
19 |
20 | /** Extends Data to provide support for ID (for findObjectInit) which is used by YubiHSM */
21 | class ExtendedData extends Data {
22 |
23 | public ExtendedData(final short opaqueObjId) {
24 | super();
25 | // The ID (CKA_ID) attribute - used by YubiHSM PKCS11 module.
26 | final ByteArrayAttribute id = new ByteArrayAttribute(Attribute.ID);
27 | id.setByteArrayValue(Bytes.ofUnsignedShort(opaqueObjId).toArrayUnsafe());
28 | attributeTable.put(Attribute.ID, id);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/keystorage/yubihsm2/src/main/java/tech/pegasys/signers/yubihsm/pkcs11/Pkcs11Session.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.yubihsm.pkcs11;
14 |
15 | import tech.pegasys.signers.yubihsm.YubiHsmException;
16 |
17 | import iaik.pkcs.pkcs11.Session;
18 | import iaik.pkcs.pkcs11.TokenException;
19 | import iaik.pkcs.pkcs11.objects.Attribute;
20 | import iaik.pkcs.pkcs11.objects.ByteArrayAttribute;
21 | import iaik.pkcs.pkcs11.objects.PKCS11Object;
22 | import org.apache.logging.log4j.LogManager;
23 | import org.apache.logging.log4j.Logger;
24 |
25 | /** Wrapper around PKCS11 session. */
26 | public class Pkcs11Session implements AutoCloseable {
27 | private static final Logger LOG = LogManager.getLogger();
28 |
29 | private final Session session;
30 |
31 | Pkcs11Session(final Session session) {
32 | this.session = session;
33 | }
34 |
35 | void initFind(PKCS11Object searchTemplate) {
36 | try {
37 | session.findObjectsInit(searchTemplate);
38 | } catch (final TokenException e) {
39 | throw new YubiHsmException("Find Initialization failed", e);
40 | }
41 | }
42 |
43 | byte[] findData() {
44 | try {
45 | final PKCS11Object[] data = session.findObjects(1);
46 | if (data == null || data.length == 0) {
47 | throw new YubiHsmException("Data not found");
48 | }
49 |
50 | return ((ByteArrayAttribute) data[0].getAttributeTable().get(Attribute.VALUE))
51 | .getByteArrayValue();
52 | } catch (final TokenException e) {
53 | throw new YubiHsmException("Data not found", e);
54 | }
55 | }
56 |
57 | void finalizeFind() {
58 | LOG.trace("Find Objects Final");
59 | try {
60 | session.findObjectsFinal();
61 | } catch (final TokenException e) {
62 | LOG.warn("PKCS11 Find finalize failed {}", e.getMessage());
63 | }
64 | }
65 |
66 | @Override
67 | public void close() {
68 | if (session != null) {
69 | logoutSession(session);
70 | closeSession(session);
71 | }
72 | }
73 |
74 | static void closeSession(final Session session) {
75 | try {
76 | session.closeSession();
77 | } catch (final TokenException closeTokenException) {
78 | LOG.warn("Unable to close session: " + closeTokenException.getMessage());
79 | }
80 | }
81 |
82 | static void logoutSession(final Session session) {
83 | try {
84 | session.logout();
85 | } catch (final TokenException e) {
86 | LOG.warn("Unable to logout session: " + e.getMessage());
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/keystorage/yubihsm2/src/main/java/tech/pegasys/signers/yubihsm/pkcs11/Pkcs11YubiHsm.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.yubihsm.pkcs11;
14 |
15 | import tech.pegasys.signers.yubihsm.YubiHsm;
16 | import tech.pegasys.signers.yubihsm.YubiHsmException;
17 |
18 | import org.apache.logging.log4j.LogManager;
19 | import org.apache.logging.log4j.Logger;
20 | import org.apache.tuweni.bytes.Bytes;
21 |
22 | public class Pkcs11YubiHsm implements YubiHsm {
23 | private static final Logger LOG = LogManager.getLogger();
24 |
25 | private final Pkcs11Session session;
26 |
27 | public Pkcs11YubiHsm(final Pkcs11Session pkcs11Session) {
28 | this.session = pkcs11Session;
29 | }
30 |
31 | @Override
32 | public synchronized Bytes fetchOpaqueData(final short opaqueObjId) throws YubiHsmException {
33 | LOG.debug("Fetching data for Opaque id {}", opaqueObjId);
34 | try {
35 | session.initFind(new ExtendedData(opaqueObjId));
36 | return Bytes.wrap(session.findData());
37 | } finally {
38 | session.finalizeFind();
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/keystorage/yubihsm2/src/main/java/tech/pegasys/signers/yubihsm/pkcs11/Pkcs11YubiHsmPin.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.yubihsm.pkcs11;
14 |
15 | public class Pkcs11YubiHsmPin {
16 | private final char[] pin;
17 |
18 | public Pkcs11YubiHsmPin(final short authId, final String password) {
19 | this.pin = String.format("%04X%s", authId, password).toCharArray();
20 | }
21 |
22 | public char[] getPin() {
23 | return pin;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/keystorage/yubihsm2/src/test/resources/log4j2-test.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 |
14 | rootProject.name='signers'
15 | include 'bls-keystore'
16 | include 'keystorage:common'
17 | include 'keystorage:hashicorp'
18 | include 'keystorage:azure'
19 | include 'keystorage:yubihsm2'
20 | include 'keystorage:interlock'
21 | include 'keystorage:aws'
22 | include 'acceptance-tests'
23 | include 'signing:secp256k1:api'
24 | include 'signing:secp256k1:impl'
25 |
--------------------------------------------------------------------------------
/signing/build.gradle:
--------------------------------------------------------------------------------
1 | jar { enabled = false }
2 |
--------------------------------------------------------------------------------
/signing/secp256k1/api/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 |
14 | jar {
15 | archiveBaseName = calculateJarName(project)
16 | manifest {
17 | attributes(
18 | 'Specification-Title': archiveBaseName,
19 | 'Specification-Version': project.version,
20 | 'Implementation-Title': archiveBaseName,
21 | 'Implementation-Version': calculateVersion()
22 | )
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/signing/secp256k1/api/src/main/java/tech/pegasys/signers/secp256k1/api/FileSelector.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.api;
14 |
15 | import java.nio.file.DirectoryStream.Filter;
16 | import java.nio.file.Path;
17 |
18 | /*
19 | A set of rules regarding how key files are to be selected.
20 | Should be overridden by the calling application to define their naming
21 | convention.
22 | */
23 | public interface FileSelector {
24 | Filter getConfigFilesFilter(T selectionCriteria);
25 | }
26 |
--------------------------------------------------------------------------------
/signing/secp256k1/api/src/main/java/tech/pegasys/signers/secp256k1/api/Signature.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.api;
14 |
15 | import java.math.BigInteger;
16 |
17 | public class Signature {
18 | private final BigInteger v;
19 | private final BigInteger r;
20 | private final BigInteger s;
21 |
22 | public Signature(final BigInteger v, final BigInteger r, final BigInteger s) {
23 | this.v = v;
24 | this.r = r;
25 | this.s = s;
26 | }
27 |
28 | public BigInteger getV() {
29 | return v;
30 | }
31 |
32 | public BigInteger getR() {
33 | return r;
34 | }
35 |
36 | public BigInteger getS() {
37 | return s;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/signing/secp256k1/api/src/main/java/tech/pegasys/signers/secp256k1/api/Signer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.api;
14 |
15 | import java.security.interfaces.ECPublicKey;
16 |
17 | public interface Signer {
18 |
19 | Signature sign(final byte[] data);
20 |
21 | ECPublicKey getPublicKey();
22 | }
23 |
--------------------------------------------------------------------------------
/signing/secp256k1/api/src/main/java/tech/pegasys/signers/secp256k1/api/SignerIdentifier.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2021 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.api;
14 |
15 | import java.security.interfaces.ECPublicKey;
16 |
17 | public interface SignerIdentifier {
18 | String toStringIdentifier();
19 |
20 | boolean validate(ECPublicKey publicKey);
21 | }
22 |
--------------------------------------------------------------------------------
/signing/secp256k1/api/src/main/java/tech/pegasys/signers/secp256k1/api/SignerProvider.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.api;
14 |
15 | import java.security.interfaces.ECPublicKey;
16 | import java.util.Optional;
17 | import java.util.Set;
18 | import java.util.function.Function;
19 |
20 | public interface SignerProvider {
21 |
22 | Optional getSigner(SignerIdentifier publicKey);
23 |
24 | Set availablePublicKeys(Function identifierFunction);
25 |
26 | default void shutdown() {}
27 | }
28 |
--------------------------------------------------------------------------------
/signing/secp256k1/api/src/main/java/tech/pegasys/signers/secp256k1/api/SingleSignerProvider.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.api;
14 |
15 | import java.security.interfaces.ECPublicKey;
16 | import java.util.Collections;
17 | import java.util.Optional;
18 | import java.util.Set;
19 | import java.util.function.Function;
20 |
21 | public class SingleSignerProvider implements SignerProvider {
22 |
23 | private final Signer signer;
24 |
25 | public SingleSignerProvider(final Signer signer) {
26 | if (signer == null) {
27 | throw new IllegalArgumentException("SingleSignerFactory requires a non-null Signer");
28 | }
29 | this.signer = signer;
30 | }
31 |
32 | @Override
33 | public Optional getSigner(final SignerIdentifier signerIdentifier) {
34 | if (signerIdentifier == null) {
35 | return Optional.empty();
36 | }
37 |
38 | return signerIdentifier.validate(signer.getPublicKey())
39 | ? Optional.of(signer)
40 | : Optional.empty();
41 | }
42 |
43 | @Override
44 | public Set availablePublicKeys(
45 | final Function identifierFunction) {
46 | return signer.getPublicKey() != null ? Set.of(signer.getPublicKey()) : Collections.emptySet();
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/signing/secp256k1/api/src/main/java/tech/pegasys/signers/secp256k1/api/util/AddressUtil.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2021 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.api.util;
14 |
15 | import java.util.Locale;
16 |
17 | public class AddressUtil {
18 | public static String remove0xPrefix(final String address) {
19 | if (address == null) {
20 | return null;
21 | }
22 |
23 | return address.toLowerCase(Locale.US).startsWith("0x") ? address.substring(2) : address;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/signing/secp256k1/build.gradle:
--------------------------------------------------------------------------------
1 | jar { enabled = false }
2 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 |
14 | apply plugin: 'java-library'
15 | apply plugin: 'java-test-fixtures'
16 |
17 | jar {
18 | archiveBaseName = calculateJarName(project)
19 | manifest {
20 | attributes(
21 | 'Specification-Title': archiveBaseName.get(),
22 | 'Specification-Version': rootProject.version,
23 | 'Implementation-Title': archiveBaseName.get(),
24 | 'Implementation-Version': calculateVersion()
25 | )
26 | }
27 | }
28 |
29 | testFixturesJar {
30 | archiveBaseName = calculateJarName(project)
31 | }
32 |
33 | dependencies {
34 |
35 | implementation project(':signing:secp256k1:api')
36 | implementation project(':keystorage:hashicorp')
37 | implementation project(':keystorage:azure')
38 |
39 | implementation 'com.google.guava:guava'
40 | implementation 'io.vertx:vertx-core'
41 | implementation 'org.apache.logging.log4j:log4j-api'
42 | implementation 'org.apache.logging.log4j:log4j-core'
43 | implementation 'org.apache.tuweni:tuweni-net'
44 | implementation 'org.apache.tuweni:tuweni-toml'
45 | implementation 'org.web3j:core'
46 | implementation 'com.azure:azure-security-keyvault-keys'
47 |
48 | runtimeOnly 'com.squareup.okhttp3:okhttp'
49 | runtimeOnly 'org.apache.logging.log4j:log4j-core'
50 | runtimeOnly 'org.apache.logging.log4j:log4j-slf4j-impl'
51 |
52 | testImplementation 'org.junit.jupiter:junit-jupiter-api'
53 | testImplementation 'org.junit.jupiter:junit-jupiter-params'
54 | testImplementation 'org.assertj:assertj-core'
55 | testImplementation 'org.mockito:mockito-inline'
56 | testImplementation 'org.mockito:mockito-core'
57 | testImplementation 'org.mockito:mockito-junit-jupiter'
58 | testImplementation(testFixtures(project(":keystorage:hashicorp")))
59 |
60 | testImplementation 'com.azure:azure-security-keyvault-keys'
61 | testImplementation 'com.azure:azure-identity'
62 |
63 | testFixturesImplementation project(':signing:secp256k1:api')
64 | testFixturesImplementation 'org.apache.tuweni:tuweni-bytes'
65 |
66 | testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
67 | }
68 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/main/java/tech/pegasys/signers/secp256k1/common/PasswordFileUtil.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.common;
14 |
15 | import static java.nio.charset.StandardCharsets.UTF_8;
16 |
17 | import java.io.IOException;
18 | import java.nio.file.Path;
19 | import java.util.Optional;
20 |
21 | import com.google.common.io.Files;
22 |
23 | public class PasswordFileUtil {
24 |
25 | /**
26 | * Read password from the first line of specified file
27 | *
28 | * @param path The file to read the password from
29 | * @return Password
30 | * @throws IOException For file operations
31 | * @throws SignerInitializationException If password file is empty
32 | */
33 | public static String readPasswordFromFile(final Path path) throws IOException {
34 | return Optional.ofNullable(Files.asCharSource(path.toFile(), UTF_8).readFirstLine()).orElse("");
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/main/java/tech/pegasys/signers/secp256k1/common/SignerInitializationException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.common;
14 |
15 | public class SignerInitializationException extends RuntimeException {
16 | public SignerInitializationException() {
17 | super();
18 | }
19 |
20 | public SignerInitializationException(final String message) {
21 | super(message);
22 | }
23 |
24 | public SignerInitializationException(final String message, final Throwable e) {
25 | super(message, e);
26 | }
27 |
28 | public SignerInitializationException(final Throwable e) {
29 | super(e);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/main/java/tech/pegasys/signers/secp256k1/filebased/CredentialSigner.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.filebased;
14 |
15 | import tech.pegasys.signers.secp256k1.EthPublicKeyUtils;
16 | import tech.pegasys.signers.secp256k1.api.Signature;
17 | import tech.pegasys.signers.secp256k1.api.Signer;
18 |
19 | import java.math.BigInteger;
20 | import java.security.interfaces.ECPublicKey;
21 |
22 | import org.web3j.crypto.Credentials;
23 | import org.web3j.crypto.Sign;
24 | import org.web3j.crypto.Sign.SignatureData;
25 |
26 | public class CredentialSigner implements Signer {
27 |
28 | private final Credentials credentials;
29 | private final ECPublicKey publicKey;
30 | private final boolean needToHash;
31 |
32 | public CredentialSigner(final Credentials credentials, final boolean needToHash) {
33 | this.credentials = credentials;
34 | this.publicKey = EthPublicKeyUtils.createPublicKey(credentials.getEcKeyPair().getPublicKey());
35 | this.needToHash = needToHash;
36 | }
37 |
38 | public CredentialSigner(final Credentials credentials) {
39 | this(credentials, true);
40 | }
41 |
42 | @Override
43 | public Signature sign(final byte[] data) {
44 | final SignatureData signature = Sign.signMessage(data, credentials.getEcKeyPair(), needToHash);
45 | return new Signature(
46 | new BigInteger(signature.getV()),
47 | new BigInteger(1, signature.getR()),
48 | new BigInteger(1, signature.getS()));
49 | }
50 |
51 | @Override
52 | public ECPublicKey getPublicKey() {
53 | return publicKey;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/main/java/tech/pegasys/signers/secp256k1/filebased/FileBasedSignerFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.filebased;
14 |
15 | import static tech.pegasys.signers.secp256k1.common.PasswordFileUtil.readPasswordFromFile;
16 |
17 | import tech.pegasys.signers.secp256k1.api.Signer;
18 | import tech.pegasys.signers.secp256k1.common.SignerInitializationException;
19 |
20 | import java.io.FileNotFoundException;
21 | import java.io.IOException;
22 | import java.nio.file.Path;
23 |
24 | import org.apache.logging.log4j.LogManager;
25 | import org.apache.logging.log4j.Logger;
26 | import org.web3j.crypto.CipherException;
27 | import org.web3j.crypto.Credentials;
28 | import org.web3j.crypto.WalletUtils;
29 |
30 | public class FileBasedSignerFactory {
31 |
32 | private static final Logger LOG = LogManager.getLogger();
33 | private static final String READ_PWD_FILE_MESSAGE = "Error when reading the password from file. ";
34 | private static final String READ_AUTH_FILE_MESSAGE =
35 | "Error when reading key file for the file based signer. ";
36 | private static final String DECRYPTING_KEY_FILE_MESSAGE =
37 | "Error when decrypting key for the file based signer. ";
38 |
39 | public static Signer createSigner(final FileSignerConfig signerConfig) {
40 | return createSigner(signerConfig.getKeystoreFile(), signerConfig.getKeystorePasswordFile());
41 | }
42 |
43 | public static Signer createSigner(final Path keyFilePath, final Path passwordFilePath) {
44 | final String password;
45 | try {
46 | password = readPasswordFromFile(passwordFilePath);
47 | } catch (final FileNotFoundException fnfe) {
48 | LOG.error("File not found: " + passwordFilePath);
49 | throw new SignerInitializationException("File not found: " + passwordFilePath);
50 | } catch (final IOException e) {
51 | final String message = READ_PWD_FILE_MESSAGE;
52 | LOG.error(message, e);
53 | throw new SignerInitializationException(message, e);
54 | }
55 | try {
56 | final Credentials credentials = WalletUtils.loadCredentials(password, keyFilePath.toFile());
57 | return new CredentialSigner(credentials);
58 | } catch (final IOException e) {
59 | final String message = READ_AUTH_FILE_MESSAGE + keyFilePath.toString();
60 | LOG.error(message, e);
61 | throw new SignerInitializationException(message, e);
62 | } catch (final CipherException e) {
63 | final String message = DECRYPTING_KEY_FILE_MESSAGE;
64 | LOG.error(message, e);
65 | throw new SignerInitializationException(message, e);
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/main/java/tech/pegasys/signers/secp256k1/filebased/FileSignerConfig.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.filebased;
14 |
15 | import java.nio.file.Path;
16 | import java.util.Objects;
17 |
18 | public class FileSignerConfig {
19 |
20 | private final Path keystoreFile;
21 | private final Path keystorePasswordFile;
22 |
23 | public FileSignerConfig(final Path keystoreFile, Path keystorePasswordFile) {
24 | this.keystoreFile = keystoreFile;
25 | this.keystorePasswordFile = keystorePasswordFile;
26 | }
27 |
28 | public Path getKeystoreFile() {
29 | return keystoreFile;
30 | }
31 |
32 | public Path getKeystorePasswordFile() {
33 | return keystorePasswordFile;
34 | }
35 |
36 | @Override
37 | public boolean equals(Object o) {
38 | if (this == o) {
39 | return true;
40 | }
41 | if (o == null || getClass() != o.getClass()) {
42 | return false;
43 | }
44 | final FileSignerConfig that = (FileSignerConfig) o;
45 | return Objects.equals(keystoreFile, that.keystoreFile)
46 | && Objects.equals(keystorePasswordFile, that.keystorePasswordFile);
47 | }
48 |
49 | @Override
50 | public int hashCode() {
51 | return Objects.hash(keystoreFile, keystorePasswordFile);
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/main/java/tech/pegasys/signers/secp256k1/hashicorp/HashicorpSignerFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.hashicorp;
14 |
15 | import tech.pegasys.signers.hashicorp.HashicorpConnection;
16 | import tech.pegasys.signers.hashicorp.HashicorpConnectionFactory;
17 | import tech.pegasys.signers.hashicorp.HashicorpException;
18 | import tech.pegasys.signers.hashicorp.config.HashicorpKeyConfig;
19 | import tech.pegasys.signers.secp256k1.api.Signer;
20 | import tech.pegasys.signers.secp256k1.common.SignerInitializationException;
21 | import tech.pegasys.signers.secp256k1.filebased.CredentialSigner;
22 |
23 | import org.web3j.crypto.Credentials;
24 |
25 | public class HashicorpSignerFactory {
26 |
27 | public HashicorpSignerFactory() {}
28 |
29 | public Signer create(final HashicorpKeyConfig keyConfig) {
30 | try (final HashicorpConnectionFactory connectionFactory = new HashicorpConnectionFactory()) {
31 | final HashicorpConnection connection =
32 | connectionFactory.create(keyConfig.getConnectionParams());
33 | final String secret = connection.fetchKey(keyConfig.getKeyDefinition());
34 | final Credentials credentials = Credentials.create(secret);
35 | return new CredentialSigner(credentials);
36 | } catch (final HashicorpException e) {
37 | throw new SignerInitializationException("Failed to extract secret from Hashicorp vault.", e);
38 | }
39 | }
40 |
41 | public void shutdown() {}
42 | }
43 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/main/java/tech/pegasys/signers/secp256k1/multikey/MultiSignerFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.multikey;
14 |
15 | import tech.pegasys.signers.secp256k1.api.Signer;
16 | import tech.pegasys.signers.secp256k1.multikey.metadata.AzureSigningMetadataFile;
17 | import tech.pegasys.signers.secp256k1.multikey.metadata.FileBasedSigningMetadataFile;
18 | import tech.pegasys.signers.secp256k1.multikey.metadata.HashicorpSigningMetadataFile;
19 | import tech.pegasys.signers.secp256k1.multikey.metadata.RawSigningMetadataFile;
20 |
21 | public interface MultiSignerFactory {
22 |
23 | Signer createSigner(AzureSigningMetadataFile metadataFile);
24 |
25 | Signer createSigner(FileBasedSigningMetadataFile metadataFile);
26 |
27 | Signer createSigner(HashicorpSigningMetadataFile metadataFile);
28 |
29 | Signer createSigner(RawSigningMetadataFile metadataFile);
30 | }
31 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/main/java/tech/pegasys/signers/secp256k1/multikey/SignerType.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.multikey;
14 |
15 | public enum SignerType {
16 | FILE_BASED_SIGNER("file-based-signer"),
17 | AZURE_SIGNER("azure-signer"),
18 | HASHICORP_SIGNER("hashicorp-signer"),
19 | RAW_SIGNER("raw-signer"),
20 | UNKNOWN_TYPE_SIGNER("unknown");
21 |
22 | private final String type;
23 |
24 | SignerType(String type) {
25 | this.type = type;
26 | }
27 |
28 | private String getType() {
29 | return type;
30 | }
31 |
32 | public static SignerType fromString(final String typeString) {
33 | for (final SignerType signerType : SignerType.values()) {
34 | if (signerType.getType().equals(typeString)) {
35 | return signerType;
36 | }
37 | }
38 | return UNKNOWN_TYPE_SIGNER;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/main/java/tech/pegasys/signers/secp256k1/multikey/TomlConfigFileParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.multikey;
14 |
15 | import static java.nio.charset.StandardCharsets.UTF_8;
16 |
17 | import java.io.File;
18 | import java.io.IOException;
19 | import java.util.stream.Collectors;
20 |
21 | import com.google.common.io.Resources;
22 | import org.apache.tuweni.toml.Toml;
23 | import org.apache.tuweni.toml.TomlParseError;
24 | import org.apache.tuweni.toml.TomlParseResult;
25 |
26 | public class TomlConfigFileParser {
27 |
28 | private static TomlParseResult loadConfiguration(final String toml) throws RuntimeException {
29 | final TomlParseResult result = Toml.parse(toml);
30 |
31 | if (result == null || result.isEmpty()) {
32 | throw new RuntimeException("Empty TOML result: " + toml);
33 | }
34 |
35 | if (result.hasErrors()) {
36 | final String errors =
37 | result.errors().stream().map(TomlParseError::toString).collect(Collectors.joining("\n"));
38 | throw new RuntimeException("Invalid TOML configuration: \n" + errors);
39 | }
40 | return result;
41 | }
42 |
43 | public static TomlParseResult loadConfigurationFromFile(final String configFilePath)
44 | throws IOException {
45 | return loadConfiguration(configTomlAsString(new File(configFilePath)));
46 | }
47 |
48 | private static String configTomlAsString(final File file) throws IOException {
49 | return Resources.toString(file.toURI().toURL(), UTF_8);
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/main/java/tech/pegasys/signers/secp256k1/multikey/TomlTableAdapter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.multikey;
14 |
15 | import java.util.Optional;
16 |
17 | import org.apache.tuweni.toml.TomlTable;
18 |
19 | public class TomlTableAdapter {
20 |
21 | private final TomlTable table;
22 |
23 | public TomlTableAdapter(final TomlTable table) {
24 | this.table = table;
25 | }
26 |
27 | public String getString(final String key) {
28 | return Optional.ofNullable(table.getString(key))
29 | .orElseThrow(() -> new IllegalArgumentException(key + " was not specified in TOML input."));
30 | }
31 |
32 | public Long getLong(final String key) {
33 | return Optional.ofNullable(table.getLong(key))
34 | .orElseThrow(() -> new IllegalArgumentException(key + " was not specified in TOML input."));
35 | }
36 |
37 | public Optional getOptionalString(final String key) {
38 | return Optional.ofNullable(table.getString(key));
39 | }
40 |
41 | public Optional getOptionalBoolean(final String key) {
42 | return Optional.ofNullable(table.getBoolean(key));
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/main/java/tech/pegasys/signers/secp256k1/multikey/metadata/AzureSigningMetadataFile.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.multikey.metadata;
14 |
15 | import tech.pegasys.signers.secp256k1.api.Signer;
16 | import tech.pegasys.signers.secp256k1.azure.AzureConfig;
17 | import tech.pegasys.signers.secp256k1.multikey.MultiSignerFactory;
18 |
19 | public class AzureSigningMetadataFile extends SigningMetadataFile {
20 |
21 | private final AzureConfig config;
22 |
23 | public AzureSigningMetadataFile(final String filename, final AzureConfig config) {
24 | super(filename);
25 | this.config = config;
26 | }
27 |
28 | public AzureConfig getConfig() {
29 | return config;
30 | }
31 |
32 | @Override
33 | public Signer createSigner(final MultiSignerFactory factory) {
34 | return factory.createSigner(this);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/main/java/tech/pegasys/signers/secp256k1/multikey/metadata/FileBasedSigningMetadataFile.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.multikey.metadata;
14 |
15 | import tech.pegasys.signers.secp256k1.api.Signer;
16 | import tech.pegasys.signers.secp256k1.filebased.FileSignerConfig;
17 | import tech.pegasys.signers.secp256k1.multikey.MultiSignerFactory;
18 |
19 | import com.google.common.base.Objects;
20 |
21 | public class FileBasedSigningMetadataFile extends SigningMetadataFile {
22 |
23 | private final FileSignerConfig config;
24 |
25 | public FileBasedSigningMetadataFile(final String filename, final FileSignerConfig config) {
26 | super(filename);
27 | this.config = config;
28 | }
29 |
30 | public FileSignerConfig getConfig() {
31 | return config;
32 | }
33 |
34 | @Override
35 | public boolean equals(final Object o) {
36 | if (this == o) {
37 | return true;
38 | }
39 | if (o == null || getClass() != o.getClass()) {
40 | return false;
41 | }
42 | final FileBasedSigningMetadataFile that = (FileBasedSigningMetadataFile) o;
43 | return Objects.equal(filename, that.filename) && Objects.equal(config, that.config);
44 | }
45 |
46 | @Override
47 | public int hashCode() {
48 | return Objects.hashCode(filename, config);
49 | }
50 |
51 | @Override
52 | public Signer createSigner(final MultiSignerFactory factory) {
53 | return factory.createSigner(this);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/main/java/tech/pegasys/signers/secp256k1/multikey/metadata/HashicorpSigningMetadataFile.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.multikey.metadata;
14 |
15 | import tech.pegasys.signers.hashicorp.config.HashicorpKeyConfig;
16 | import tech.pegasys.signers.secp256k1.api.Signer;
17 | import tech.pegasys.signers.secp256k1.multikey.MultiSignerFactory;
18 |
19 | public class HashicorpSigningMetadataFile extends SigningMetadataFile {
20 |
21 | private final HashicorpKeyConfig hashicorpConfig;
22 |
23 | public HashicorpSigningMetadataFile(
24 | final String filename, final HashicorpKeyConfig hashicorpConfig) {
25 | super(filename);
26 | this.hashicorpConfig = hashicorpConfig;
27 | }
28 |
29 | public HashicorpKeyConfig getConfig() {
30 | return hashicorpConfig;
31 | }
32 |
33 | @Override
34 | public Signer createSigner(final MultiSignerFactory factory) {
35 | return factory.createSigner(this);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/main/java/tech/pegasys/signers/secp256k1/multikey/metadata/RawSigningMetadataFile.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.multikey.metadata;
14 |
15 | import tech.pegasys.signers.secp256k1.api.Signer;
16 | import tech.pegasys.signers.secp256k1.multikey.MultiSignerFactory;
17 |
18 | public class RawSigningMetadataFile extends SigningMetadataFile {
19 |
20 | private final String privKey;
21 |
22 | public RawSigningMetadataFile(final String filename, final String privKey) {
23 | super(filename);
24 | this.privKey = privKey;
25 | }
26 |
27 | @Override
28 | public Signer createSigner(final MultiSignerFactory factory) {
29 | return factory.createSigner(this);
30 | }
31 |
32 | public String getPrivKey() {
33 | return privKey;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/main/java/tech/pegasys/signers/secp256k1/multikey/metadata/SigningMetadataFile.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.multikey.metadata;
14 |
15 | import tech.pegasys.signers.secp256k1.api.Signer;
16 | import tech.pegasys.signers.secp256k1.multikey.MultiSignerFactory;
17 |
18 | public abstract class SigningMetadataFile {
19 |
20 | protected String filename;
21 |
22 | public SigningMetadataFile(final String filename) {
23 | this.filename = filename;
24 | }
25 |
26 | public String getFilename() {
27 | return filename;
28 | }
29 |
30 | public abstract Signer createSigner(final MultiSignerFactory factory);
31 | }
32 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/test/java/tech/pegasys/signers/secp256k1/common/PasswordFileUtilTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.common;
14 |
15 | import static java.nio.charset.StandardCharsets.UTF_8;
16 | import static org.assertj.core.api.Assertions.assertThat;
17 |
18 | import java.io.IOException;
19 | import java.nio.file.Files;
20 | import java.nio.file.Path;
21 |
22 | import org.junit.jupiter.api.Test;
23 | import org.junit.jupiter.api.io.TempDir;
24 | import org.junit.jupiter.params.ParameterizedTest;
25 | import org.junit.jupiter.params.provider.ValueSource;
26 |
27 | class PasswordFileUtilTest {
28 |
29 | @ParameterizedTest
30 | @ValueSource(strings = {"line1\nline2", "line1\n", "line1"})
31 | void canReadPasswordFromFile(final String content, @TempDir final Path tempDir)
32 | throws IOException {
33 | final Path passwordFile = Files.write(tempDir.resolve("password.txt"), content.getBytes(UTF_8));
34 | assertThat(PasswordFileUtil.readPasswordFromFile(passwordFile)).isEqualTo("line1");
35 | }
36 |
37 | @Test
38 | void canReadSpaceOnlyPasswordFromFile(@TempDir final Path tempDir) throws IOException {
39 | final Path passwordFile = Files.write(tempDir.resolve("password.txt"), " \n".getBytes(UTF_8));
40 | assertThat(PasswordFileUtil.readPasswordFromFile(passwordFile)).isEqualTo(" ");
41 | }
42 |
43 | @ParameterizedTest
44 | @ValueSource(strings = {"", "\n"})
45 | void canReadPasswordFromEmptyStringFile(final String content, @TempDir final Path tempDir)
46 | throws IOException {
47 | final Path passwordFile = Files.write(tempDir.resolve("password.txt"), content.getBytes(UTF_8));
48 | assertThat(PasswordFileUtil.readPasswordFromFile(passwordFile)).isEqualTo("");
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/test/java/tech/pegasys/signers/secp256k1/filebased/CredentialSignerTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.filebased;
14 |
15 | import static java.nio.charset.StandardCharsets.UTF_8;
16 | import static org.assertj.core.api.Assertions.assertThat;
17 |
18 | import java.math.BigInteger;
19 |
20 | import org.junit.jupiter.api.Test;
21 | import org.web3j.crypto.Credentials;
22 | import org.web3j.crypto.ECKeyPair;
23 | import org.web3j.crypto.Hash;
24 |
25 | class CredentialSignerTest {
26 |
27 | @Test
28 | void needToHashFlagAffectsProducedSignature() {
29 | final Credentials credentials = Credentials.create(ECKeyPair.create(BigInteger.ONE));
30 |
31 | final CredentialSigner hashingSigner = new CredentialSigner(credentials);
32 | final CredentialSigner nonHashingSigner = new CredentialSigner(credentials, false);
33 |
34 | final byte[] data = "Hello World".getBytes(UTF_8);
35 |
36 | assertThat(hashingSigner.getPublicKey().getEncoded())
37 | .isEqualTo(nonHashingSigner.getPublicKey().getEncoded());
38 | assertThat(hashingSigner.sign(data))
39 | .isEqualToComparingFieldByField(nonHashingSigner.sign(Hash.sha3(data)));
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/test/java/tech/pegasys/signers/secp256k1/multikey/FileBasedSigningMetadataFileTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.multikey;
14 |
15 | import static org.assertj.core.api.Assertions.assertThat;
16 | import static tech.pegasys.signers.secp256k1.multikey.MetadataFileFixture.CONFIG_FILE_EXTENSION;
17 | import static tech.pegasys.signers.secp256k1.multikey.MetadataFileFixture.KEY_FILE;
18 | import static tech.pegasys.signers.secp256k1.multikey.MetadataFileFixture.LOWERCASE_ADDRESS;
19 | import static tech.pegasys.signers.secp256k1.multikey.MetadataFileFixture.PASSWORD_FILE;
20 | import static tech.pegasys.signers.secp256k1.multikey.MetadataFileFixture.PREFIX_ADDRESS;
21 | import static tech.pegasys.signers.secp256k1.multikey.MetadataFileFixture.load;
22 |
23 | import tech.pegasys.signers.secp256k1.multikey.metadata.FileBasedSigningMetadataFile;
24 |
25 | import org.junit.jupiter.api.Test;
26 |
27 | class FileBasedSigningMetadataFileTest {
28 |
29 | @Test
30 | void matchingMetadataFileWithoutPrefixShouldHaveExpectedName() {
31 | final FileBasedSigningMetadataFile fileBasedSigningMetadataFile =
32 | load(LOWERCASE_ADDRESS + CONFIG_FILE_EXTENSION, KEY_FILE, PASSWORD_FILE);
33 |
34 | assertThat(fileBasedSigningMetadataFile.getFilename())
35 | .matches(LOWERCASE_ADDRESS + CONFIG_FILE_EXTENSION);
36 | assertThat(fileBasedSigningMetadataFile.getConfig().getKeystoreFile().toFile().toString())
37 | .matches(KEY_FILE);
38 | assertThat(
39 | fileBasedSigningMetadataFile.getConfig().getKeystorePasswordFile().toFile().toString())
40 | .matches(PASSWORD_FILE);
41 | }
42 |
43 | @Test
44 | void matchingMetadataFileWithPrefixShouldHaveExpectedName() {
45 | final String prefix = "bar_";
46 | final FileBasedSigningMetadataFile fileBasedSigningMetadataFile =
47 | load(prefix + PREFIX_ADDRESS + CONFIG_FILE_EXTENSION, KEY_FILE, PASSWORD_FILE);
48 |
49 | assertThat(fileBasedSigningMetadataFile.getFilename())
50 | .matches(prefix + PREFIX_ADDRESS + CONFIG_FILE_EXTENSION);
51 | assertThat(fileBasedSigningMetadataFile.getConfig().getKeystoreFile().toFile().toString())
52 | .matches(KEY_FILE);
53 | assertThat(
54 | fileBasedSigningMetadataFile.getConfig().getKeystorePasswordFile().toFile().toString())
55 | .matches(PASSWORD_FILE);
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/test/resources/metadata-toml-configs/627306090abab3a6e1400e9345bc60c78a8bef57.toml:
--------------------------------------------------------------------------------
1 | [metadata]
2 | createdAt = 1994-11-05T08:15:30-05:00
3 | description = "Example of File based configuration"
4 |
5 | [signing]
6 | type = "file-based-signer"
7 | key-file = "/path/to/k.key"
8 | password-file = "/path/to/p.password"
9 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/test/resources/metadata-toml-configs/UTC--2019-10-23T04-00-04.860366000Z--f17f52151ebef6c7334fad080c5704d77216b732.toml:
--------------------------------------------------------------------------------
1 | [metadata]
2 | createdAt = 1994-11-05T08:15:30-05:00
3 | description = "Example of File based configuration"
4 |
5 | [signing]
6 | type = "file-based-signer"
7 | key-file = "/path/to/k.key"
8 | password-file = "/path/to/p.password"
9 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/test/resources/metadata-toml-configs/azureconfig.toml:
--------------------------------------------------------------------------------
1 | [metadata]
2 | createdAt = 2011-11-01T12:15:30Z
3 | description = "Example of Azure Key Vault based configuration"
4 |
5 | [signing]
6 | type = "azure-signer"
7 | key-vault-name = "testkey"
8 | key-name = "TestKey"
9 | key-version = "7c01fe58d68148bba5824ce418241092"
10 | client-id = "theClientId"
11 | client-secret = "theClientSecret"
12 | tenant-id = "theTenantId"
13 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/test/resources/metadata-toml-configs/azureconfig_illegalValueType.toml:
--------------------------------------------------------------------------------
1 | [metadata]
2 | createdAt = 2011-11-01T12:15:30Z
3 | description = "Example of Azure Key Vault based configuration"
4 |
5 | [signing]
6 | type = "azure-signer"
7 | key-vault-name = 9
8 | key-name = "TestKey"
9 | key-version = "7c01fe58d68148bba5824ce418241092"
10 | client-id = "theClientId"
11 | client-secret = "theClientSecret"
12 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/test/resources/metadata-toml-configs/azureconfig_missingField.toml:
--------------------------------------------------------------------------------
1 | [metadata]
2 | createdAt = 2011-11-01T12:15:30Z
3 | description = "Example of Azure Key Vault based configuration"
4 |
5 | [signing]
6 | type = "azure-signer"
7 | key-name = "TestKey"
8 | key-version = "7c01fe58d68148bba5824ce418241092"
9 | client-id = "theClientId"
10 | client-secret = "theClientSecret"
11 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/test/resources/metadata-toml-configs/bar_fe3b557e8fb62b89f4916b721be55ceb828dbd73.toml:
--------------------------------------------------------------------------------
1 | [metadata]
2 | createdAt = 1994-11-05T08:15:30-05:00
3 | description = "Example of File based configuration"
4 |
5 | [signing]
6 | type = "file-based-signer"
7 | key-file = "/path/to/k2.key"
8 | password-file = "/path/to/p2.password"
9 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/test/resources/metadata-toml-configs/duplicate_bar_627306090abab3a6e1400e9345bc60c78a8bef61.toml:
--------------------------------------------------------------------------------
1 | [metadata]
2 | createdAt = 1994-11-05T08:15:30-05:00
3 | description = "Example of File based configuration"
4 |
5 | [signing]
6 | type = "file-based-signer"
7 | key-file = "/path/to/k2.key"
8 | password-file = "/path/to/p2.password"
9 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/test/resources/metadata-toml-configs/duplicate_foo_627306090abab3a6e1400e9345bc60c78a8bef61.toml:
--------------------------------------------------------------------------------
1 | [metadata]
2 | createdAt = 1994-11-05T08:15:30-05:00
3 | description = "Example of File based configuration"
4 |
5 | [signing]
6 | type = "file-based-signer"
7 | key-file = "/path/to/k.key"
8 | password-file = "/path/to/p.password"
9 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/test/resources/metadata-toml-configs/k.key:
--------------------------------------------------------------------------------
1 | {"version":3,"id":"2fe66c68-f643-4a8a-9672-427d0456e1ba","address":"4897b54979b9bf339f13dd461628476430cf0ea5","crypto":{"ciphertext":"6488cd65ea6654c1a5083e8d93e63144250f5616785c8960eed71f76de52a6d7","cipherparams":{"iv":"ae0c07bea178acfdd31f10cb34efb18a"},"cipher":"aes-128-ctr","kdf":"scrypt","kdfparams":{"dklen":32,"salt":"10d0fd16d66de3351bed29b6cb3839f18beafeaabe8831bb456e7b421c4187d9","n":8192,"r":8,"p":1},"mac":"4326717f0225b3e05fe0b97fe0f0882a542042c212e5ed99297de112d7a923d0"}}
2 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/test/resources/metadata-toml-configs/key_password_relative_path.toml:
--------------------------------------------------------------------------------
1 | [metadata]
2 | createdAt = 1994-11-05T08:15:30-05:00
3 | description = "Example of File based configuration"
4 |
5 | [signing]
6 | type = "file-based-signer"
7 | key-file = "./path/to/k.key"
8 | password-file = "./path/to/p.password"
9 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/test/resources/metadata-toml-configs/missing_key_and_password_file_fe3b557e8fb62b89f4916b721be55ceb828dbd78.toml:
--------------------------------------------------------------------------------
1 | [metadata]
2 | createdAt = 1994-11-05T08:15:30-05:00
3 | description = "Example of File based configuration"
4 |
5 | [signing]
6 | type = "file-based-signer"
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/test/resources/metadata-toml-configs/missing_key_file_fe3b557e8fb62b89f4916b721be55ceb828dbd76.toml:
--------------------------------------------------------------------------------
1 | [metadata]
2 | createdAt = 1994-11-05T08:15:30-05:00
3 | description = "Example of File based configuration"
4 |
5 | [signing]
6 | type = "file-based-signer"
7 | password-file = "/path/to/p2.password"
8 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/test/resources/metadata-toml-configs/missing_password_file_fe3b557e8fb62b89f4916b721be55ceb828dbd77.toml:
--------------------------------------------------------------------------------
1 | [metadata]
2 | createdAt = 1994-11-05T08:15:30-05:00
3 | description = "Example of File based configuration"
4 |
5 | [signing]
6 | type = "file-based-signer"
7 | key-file = "/path/to/k2.key"
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/test/resources/metadata-toml-configs/p.password:
--------------------------------------------------------------------------------
1 | pantheon
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/test/resources/metadata-toml-configs/unknown_type_signer_fe3b557e8fb62b89f4916b721be55ceb828dbd75.toml:
--------------------------------------------------------------------------------
1 | [metadata]
2 | createdAt = 1994-11-05T08:15:30-05:00
3 | description = "Example of File based configuration"
4 |
5 | [signing]
6 | type = "unknown-type-signer"
7 | key-file = "/path/to/k2.key"
8 | password-file = "/path/to/p2.password"
9 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/testFixtures/java/tech/pegasys/signers/secp256k1/common/PublicKeySignerIdentifier.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2021 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.common;
14 |
15 | import static tech.pegasys.signers.secp256k1.api.util.AddressUtil.remove0xPrefix;
16 |
17 | import tech.pegasys.signers.secp256k1.EthPublicKeyUtils;
18 | import tech.pegasys.signers.secp256k1.api.SignerIdentifier;
19 |
20 | import java.security.interfaces.ECPublicKey;
21 |
22 | public class PublicKeySignerIdentifier implements SignerIdentifier {
23 | private final ECPublicKey publicKey;
24 |
25 | public PublicKeySignerIdentifier(final ECPublicKey publicKey) {
26 | this.publicKey = publicKey;
27 | }
28 |
29 | @Override
30 | public String toStringIdentifier() {
31 | return remove0xPrefix(EthPublicKeyUtils.toHexString(publicKey));
32 | }
33 |
34 | @Override
35 | public boolean validate(final ECPublicKey publicKey) {
36 | return EthPublicKeyUtils.toHexString(this.publicKey)
37 | .equalsIgnoreCase(EthPublicKeyUtils.toHexString(publicKey));
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/signing/secp256k1/impl/src/testFixtures/java/tech/pegasys/signers/secp256k1/common/TomlStringBuilder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 ConsenSys AG.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. 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 distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package tech.pegasys.signers.secp256k1.common;
14 |
15 | /** Create toml String with header. Note: To be used in tests only. */
16 | public class TomlStringBuilder {
17 | private final StringBuilder stringBuilder = new StringBuilder();
18 |
19 | public TomlStringBuilder(final String header) {
20 | stringBuilder.append(String.format("[%s]\n", header));
21 | }
22 |
23 | public TomlStringBuilder withQuotedString(final String key, final String value) {
24 | stringBuilder.append(String.format("%s=\"%s\"\n", key, value));
25 | return this;
26 | }
27 |
28 | public TomlStringBuilder withNonQuotedString(final String key, final String value) {
29 | stringBuilder.append(String.format("%s=%s\n", key, value));
30 | return this;
31 | }
32 |
33 | public String build() {
34 | return stringBuilder.toString();
35 | }
36 | }
37 |
--------------------------------------------------------------------------------