-
Notifications
You must be signed in to change notification settings - Fork 157
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
"This code is a Contribution to the OpenConfig Feature Profiles project ("Work") made under the Google Software Grant and Corporate Contributor License Agreement ("CLA") and governed by the Apache License 2.0. No other rights or licenses in or to any of Nokia's intellectual property are granted for any other purpose. This code is provided on an "as is" basis without any warranties of any kind."
- Loading branch information
Showing
12 changed files
with
1,482 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# attestz-2: Validate oIAK and oIDevID rotation | ||
|
||
## Summary | ||
|
||
In TPM enrollment workflow the switch owner verifies device's Initial Attestation Key (IAK) and Initial DevID (IDevID) certificates (signed by the switch vendor CA) and installs/rotates owner IAK (oIAK) and owner IDevID (oIDevID) certificates (signed by switch owner CA). In TPM attestation workflow switch owner verifies that the device's end-to-end boot state (bootloader, OS, secure boot policy, etc.) matches owner's expectations. | ||
|
||
## Procedure | ||
|
||
Test should verify all success and failure/corner-case scenarios for TPM enrollment and attestation workflows that are specified in [attestz Readme](https://github.com/openconfig/attestz/blob/main/README.md). | ||
|
||
TPM enrollment workflow consists of two APIs defined in openconfig/attestz/blob/main/proto/tpm_enrollz.proto: `GetIakCert` and `RotateOIakCert`. | ||
TPM attestation workflow consists of a single API defined in openconfig/attestz/blob/main/proto/tpm_attestz.proto: `Attest`. | ||
The tests should comprehensively cover the behavior for all three APIs when used both separately and sequentially. | ||
Finally, the tests should cover both initial install/bootstrapping, oIAK/oIDevID rotation and post-install re-attestation workflows. | ||
|
||
## Test Setup | ||
|
||
1. Switch vendor provisioned the device with IAK and IDevID certs following TCG spec [Section 5.2](https://trustedcomputinggroup.org/wp-content/uploads/TPM-2p0-Keys-for-Device-Identity-and-Attestation_v1_r12_pub10082021.pdf#page=20) and [Section 6.2](https://trustedcomputinggroup.org/wp-content/uploads/TPM-2p0-Keys-for-Device-Identity-and-Attestation_v1_r12_pub10082021.pdf#page=30). | ||
2. The device successfully completed the bootz workflow where it obtained and applied all configurations/credentials/certificates and booted into the right OS image. | ||
3. Device is serving `enrollz` and `attestz` gRPC endpoints. | ||
|
||
### attestz-2: Validate oIAK and oIDevID rotation | ||
|
||
The test validates that the device can rotate oIAK and oIDevID certificates post-install. | ||
|
||
| ID | Case | Result | | ||
| ----------- | ----------------| ------ | | ||
| attestz-2.1 | Successful oIAK and oIDevID cert rotation when no owner-issued mTLS cert is available on the device | Device obtained newly-rotated oIAK and oIDevID certs and passed attestation for all control cards relying on the new oIAK and oIDevID certs | | ||
| attestz-2.2 | Successful oIAK and oIDevID cert rotation when owner-issued mTLS cert is available on the device | Device obtained newly-rotated oIAK and oIDevID certs and passed attestation for all control cards relying on the new oIAK and previously owner-issued mTLS cert | | ||
| attestz-2.3 | Device is unable to authenticate switch owner (e.g. no suitable TLS trust bundle) during oIAK/oIDevID rotation | Both `GetIakCert` and `RotateOIakCert` return authentication failure error | | ||
|
||
1. Execute "Initial Install" workflow. | ||
2. Issue new oIAK and oIDevID certs for active control card, call `RotateOIakCert` to store those on the right card and verify successful response. | ||
3. Issue new oIAK and oIDevID certs for standby control card, call `RotateOIakCert` to store those on the right card and verify successful response. | ||
4. Call `Attest` for active and standby control cards and ensure they use the latest oIAK for attestation and, if there is no owner-provisioned TLS cert installed, use latest oIDevID for TLS session. | ||
5. Do the same verification of attestation responses as in "Initial Install" workflow. | ||
|
||
## OpenConfig Path and RPC Coverage | ||
|
||
The below yaml defines the OC paths intended to be covered by this test. OC paths used for test setup are not listed here. | ||
|
||
```yaml | ||
rpcs: | ||
gnsi: | ||
certz.v1.Certz.Rotate: | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
// Copyright 2024 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package attestz2 | ||
|
||
import ( | ||
"context" | ||
"flag" | ||
"fmt" | ||
"strings" | ||
"testing" | ||
|
||
enrollzpb "github.com/openconfig/attestz/proto/tpm_enrollz" | ||
"github.com/openconfig/featureprofiles/internal/fptest" | ||
"github.com/openconfig/featureprofiles/internal/security/attestz" | ||
"github.com/openconfig/ondatra" | ||
"github.com/openconfig/ondatra/gnmi" | ||
"google.golang.org/grpc/codes" | ||
"google.golang.org/grpc/status" | ||
) | ||
|
||
var ( | ||
vendorCaCertPem = flag.String("switch_vendor_ca_cert", "", "a pem file for vendor ca cert used for verifying iDevID/IAK Certs") | ||
ownerCaCertPem = flag.String("switch_owner_ca_cert", "../testdata/owner-ca.cert.pem", "a pem file for ca cert that will be used to sign oDevID/oIAK/mTLS Certs") | ||
ownerCaKeyPem = flag.String("switch_owner_ca_key", "../testdata/owner-ca.key.pem", "a pem file for ca key that will be used to sign oDevID/oIAK/mTLS Certs") | ||
) | ||
|
||
func TestMain(m *testing.M) { | ||
fptest.RunTests(m) | ||
} | ||
|
||
func TestAttestz2(t *testing.T) { | ||
dut := ondatra.DUT(t, "dut") | ||
// Retrieve vendor ca certificate from testdata if not provided in test args. | ||
if *vendorCaCertPem == "" { | ||
*vendorCaCertPem = fmt.Sprintf("../testdata/%s-ca.cert.pem", strings.ToLower(dut.Vendor().String())) | ||
} | ||
|
||
attestzTarget, attestzServer := attestz.SetupBaseline(t, dut) | ||
t.Cleanup(func() { | ||
gnmi.Delete(t, dut, gnmi.OC().System().GrpcServer(*attestzServer.Name).Config()) | ||
attestz.DeleteProfile(t, dut, *attestzServer.SslProfileId) | ||
}) | ||
tc := &attestz.TLSConf{ | ||
Target: attestzTarget, | ||
CaKeyFile: *ownerCaKeyPem, | ||
CaCertFile: *ownerCaCertPem, | ||
} | ||
|
||
// Find active & standby card. | ||
activeCard, standbyCard := attestz.FindControlCards(t, dut) | ||
|
||
// Execute initial install workflow. | ||
activeCard.EnrollzWorkflow(t, dut, tc, *vendorCaCertPem) | ||
standbyCard.EnrollzWorkflow(t, dut, tc, *vendorCaCertPem) | ||
activeCard.AttestzWorkflow(t, dut, tc) | ||
standbyCard.AttestzWorkflow(t, dut, tc) | ||
|
||
t.Run("Attestz-2.1 - Successful enrollz w/o mTLS", func(t *testing.T) { | ||
// Re-enroll for active & standby card. | ||
activeCard.EnrollzWorkflow(t, dut, tc, *vendorCaCertPem) | ||
standbyCard.EnrollzWorkflow(t, dut, tc, *vendorCaCertPem) | ||
|
||
// Re-attest for active & standby card. | ||
activeCard.AttestzWorkflow(t, dut, tc) | ||
standbyCard.AttestzWorkflow(t, dut, tc) | ||
}) | ||
|
||
t.Run("Attestz-2.2 - Successful enrollz with mTLS", func(t *testing.T) { | ||
// Enable mtls. | ||
tc.EnableMtls(t, dut, *attestzServer.SslProfileId) | ||
activeCard.MtlsCert = string(tc.ServerCert) | ||
standbyCard.MtlsCert = string(tc.ServerCert) | ||
|
||
// Re-enroll for active & standby card with mtls. | ||
activeCard.EnrollzWorkflow(t, dut, tc, *vendorCaCertPem) | ||
activeCard.MtlsCert = "" | ||
standbyCard.EnrollzWorkflow(t, dut, tc, *vendorCaCertPem) | ||
|
||
// Re-attest for active & standby card. | ||
activeCard.AttestzWorkflow(t, dut, tc) | ||
standbyCard.AttestzWorkflow(t, dut, tc) | ||
}) | ||
|
||
t.Run("Attestz-2.3 - enrollz with invalid trust bundle", func(t *testing.T) { | ||
// Server certificate can be used to simulate an invalid trust-bundle. | ||
attestz.RotateCerts(t, dut, attestz.CertTypeRaw, *attestzServer.SslProfileId, nil, nil, tc.ServerCert) | ||
|
||
as := tc.NewSession(t) | ||
_, err := as.EnrollzClient.GetIakCert(context.Background(), &enrollzpb.GetIakCertRequest{}) | ||
if err == nil { | ||
t.Fatalf("GetIakCert rpc succeeded but expected to fail.") | ||
} | ||
if status.Code(err) != codes.Unauthenticated { | ||
t.Errorf("Did not receive expected error code for GetIakCert rpc. got error: %v, want error: Unauthenticated", err) | ||
} | ||
t.Logf("Got expected error for GetIakCert rpc. error: %v", err) | ||
|
||
_, err = as.EnrollzClient.RotateOIakCert(context.Background(), &enrollzpb.RotateOIakCertRequest{}) | ||
if err == nil { | ||
t.Fatalf("RotateOIakCert rpc succeeded but expected to fail.") | ||
} | ||
if status.Code(err) != codes.Unauthenticated { | ||
t.Errorf("Did not receive expected error code for RotateOIakCert rpc. got error: %v, want error: Unauthenticated", err) | ||
} | ||
t.Logf("Got expected error for RotateOIakCert rpc. error: %v", err) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# proto-file: github.com/openconfig/featureprofiles/proto/metadata.proto | ||
# proto-message: Metadata | ||
|
||
uuid: "7378f860-e39e-4239-b233-deda1d7bd9db" | ||
plan_id: "attestz-2" | ||
description: "Validate oIAK and oIDevID rotation" | ||
testbed: TESTBED_DUT |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
-----BEGIN CERTIFICATE----- | ||
MIIGYDCCBEigAwIBAgIUePsHg1oV7Q1GdF/9M4IkIAY+F4gwDQYJKoZIhvcNAQEM | ||
BQAwSTELMAkGA1UEBhMCVVMxDjAMBgNVBAoTBU5va2lhMSowKAYDVQQDEyFOb2tp | ||
YSBJUCBOZXR3b3JrcyBGYWN0b3J5IFJvb3QgQ0EwIBcNMjMxMDEwMTU1MzU1WhgP | ||
MjA3MzEwMDkxNTM5MDhaMEUxCzAJBgNVBAYTAlVTMQ4wDAYDVQQKEwVOb2tpYTEm | ||
MCQGA1UEAxMdTm9raWEgSVAgTmV0d29ya3MgRmFjdG9yeSBDQTEwggIiMA0GCSqG | ||
SIb3DQEBAQUAA4ICDwAwggIKAoICAQDDfVpJ/ji15e6DdMCrPNogqUOb6zQp1koV | ||
r+TlfUVlh0b3yorrZG4JGhqRc/VQ7qdBx1jpywQa7P6lqDREhWKWGa3UBD2BtyIC | ||
jZaujQIHIM3rzA5qtgitj8YRLEsKvCqL4JsdMbsqGZPYC2Q7lWRJqSZwfnhx0vPm | ||
hYOjQn+gbnzWDbKbHkYUTsS6eC4ReVYEk4YlxcjJcabRb0w3OAj3i3u1F2T0F37b | ||
JUQWu94Pf4J9o8/thEdt2LfCeKDxbwX72q4zymGo77zruh0bHhi0KbsKGA6uF1+p | ||
sw2TjnDo19GzjpEW+ySp07fYGapke2oKpIsJJ0DUmjg/WL0lFZa3BTBzTDHZq4nu | ||
cE5B2zqkdiq7ra6ozMmM0aBIqUMYrvjOtdXWniQL6VFlnmHD1+pUFUm1b3BUwCP3 | ||
ydTwzKk1E7xBVb88aInOOVO08WyYBEJ8t8Rap8P1TWjkXrh3YCuxACgiqx+E02ct | ||
lXYX4m6XKD8moMe81AGoM1O5ATv+phPHwpSNoEtBIjk1DX2bdNwVnBBKq/8yh7ey | ||
o9sH9TK9SHCHaZt44Uwxqw7X885/MlbMwI/lFX9JRfx1o8qkN8lUWPvQ76nV+PKp | ||
shBq2J2FzWnm+HdMMYlMQav8C1V2LBjWTWna6iNv+1We0lMJZno31v4xlCwYOQqe | ||
Xvzafx3xeQIDAQABo4IBQDCCATwwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4E | ||
FgQUOhNBkE077lmEbT2/UGPOUjVk8yswHwYDVR0jBBgwFoAU/yqnjcq4acjk81OE | ||
20uGv2+Gxl0wDgYDVR0PAQH/BAQDAgGGMIGGBggrBgEFBQcBAQR6MHgwKAYIKwYB | ||
BQUHMAGGHGh0dHA6Ly9vY3NwLm9uZS5kaWdpY2VydC5jb20wTAYIKwYBBQUHMAKG | ||
QGh0dHA6Ly9jYWNlcnRzLm9uZS5kaWdpY2VydC5jb20vTm9raWFJUE5ldHdvcmtz | ||
RmFjdG9yeVJvb3RDQS5jcnQwTQYDVR0fBEYwRDBCoECgPoY8aHR0cDovL2NybC5v | ||
bmUuZGlnaWNlcnQuY29tL05va2lhSVBOZXR3b3Jrc0ZhY3RvcnlSb290Q0EuY3Js | ||
MA0GCSqGSIb3DQEBDAUAA4ICAQCVYEVn/RyiM3ybOn1+BA0+0sqBiLM6I6BBPGuq | ||
9JQvdHETIkdd5VI2/5BLc1ZcBatLmlJkYW8rUDfZLU1Hv8IHpBbH6TWEBjNo5mtF | ||
aY4UhHWiEOUAP5cboxIjR8F2SmSONvIMvIIoG8HKr6UupQx264TxMgdKmctjbAuI | ||
BcCitZNEG0M6l4bwI4dlbbEuI0sh4l5TpThmzXrYSt7zyvrpajRmcwHFpX9tq6aH | ||
dt2FEELY/JLQaZvVnIHcdWnhMyG1nonALbxV8HWC6gr9mwoBWLRK9tcwsyw2q88R | ||
J1HevqJWABSdwVydh5OhnViLq9i8u3BxnMegzqM6R8mYPHTaZSl1FXb6uQmp6V2y | ||
40kg4D8sSn5jkLtovStu7uqAGTZTR1/Ld2KF3fSv8ZxeX+ia4lPRxSpoOTXeTIfa | ||
E7bIPBVhw636gEs/Ztz6T90Pzs5qNhQ1bQlFfqBlZyXmG2q2PwJwcQkjiuJ4LWNg | ||
JO1p8Es6E/wy3HB9ymY4dpSqoyd1ZkGEKA0+L1AFkhizUsi7EgGge9Il49AtQiyp | ||
lvuJ0m+94MEaNVJUxMVVVWkRAM5DxVKTcAAq1iP/m6hPSMwlN9+NA+d1fekvrHEF | ||
xomnozUoWQ0lHeewDVNblSAvGGRZUZ2AI7PnQ2NPaZRA9b8/wdTl3NL/yfv/vN+8 | ||
BIpY5Q== | ||
-----END CERTIFICATE----- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
-----BEGIN CERTIFICATE----- | ||
MIIDmzCCAoOgAwIBAgIUDG5yZigPNdiefkggL803LqhyxFgwDQYJKoZIhvcNAQEL | ||
BQAwXTEQMA4GA1UEAwwHQ0EgMDAwMTELMAkGA1UEBhMCQVExCzAJBgNVBAgMAk5a | ||
MQswCQYDVQQHDAJOWjEiMCAGA1UECgwZT3BlbkNvbmZpZ0ZlYXR1cmVQcm9maWxl | ||
czAeFw0yNDA0MDExODUxNDNaFw0zNDAzMzAxODUxNDNaMF0xEDAOBgNVBAMMB0NB | ||
IDAwMDExCzAJBgNVBAYTAkFRMQswCQYDVQQIDAJOWjELMAkGA1UEBwwCTloxIjAg | ||
BgNVBAoMGU9wZW5Db25maWdGZWF0dXJlUHJvZmlsZXMwggEiMA0GCSqGSIb3DQEB | ||
AQUAA4IBDwAwggEKAoIBAQC6V1P/Zj6s0yCiw3CY2mq79iUdVnj72xwZ3me9/oU+ | ||
HZaOvmUoyTEg3KJGIIBZCTE4EZG0BFbjtkeuQWzYJviYUBphZyv7dURnNFyJcYWk | ||
jLjk1aX3ynx0X+PGrLtECe/Fn3wfdjSg3qA39g0I+ZneeXeRMidXZFnvk/YJQnAn | ||
UHTa9/raDAQoYtnNmzm+5meRo00BQR4rJuJJJg1+67fSSy3i6OQfFlC+eeGTyyjH | ||
9hcAwrN48TVVv6IRcljyUX1GF0YpcdfpQXK6S7JCDSrwzTJeifcBN/2xPvqHb0fU | ||
S4hIVtMy6KwUvaL7miKXxRJE6BFAQ1nhQCUQP+DBSNmnAgMBAAGjUzBRMB0GA1Ud | ||
DgQWBBQzvHg3d3iZkDfSqtcX7xoSHisAyDAfBgNVHSMEGDAWgBQzvHg3d3iZkDfS | ||
qtcX7xoSHisAyDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBu | ||
VecPw0rw1gqnaH0M7qAjaayvo7AJyWhWSF3yFcsC/Wa/8xcaCQ2Rz+2g5di8E6n+ | ||
fLb18rpFnt+vmUplz98ooqJeMYb6POCqGpu1dJU+utIzBYjYh4xld6UeR+KEnmuZ | ||
IQF4ryLrBr9/CLgKv33AUw+XiTROkRf5+BaCgz/LgUENXSKtRJBMFSaNxpWnd0zy | ||
WHveqEkyIV8XPFY186YjWiCW4hJ2M1yKhiotnOdUih7KXyOrv9lpzkLnSnW2wbtw | ||
MH1kM7IfD2VAMO65o0wybF0Pzd+hALYGdO9A6QR9XwHZxyRKH4rPo3mVrzjeDubL | ||
CPL/t7xS1FIL5Y+XTdkM | ||
-----END CERTIFICATE----- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
-----BEGIN PRIVATE KEY----- | ||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC6V1P/Zj6s0yCi | ||
w3CY2mq79iUdVnj72xwZ3me9/oU+HZaOvmUoyTEg3KJGIIBZCTE4EZG0BFbjtkeu | ||
QWzYJviYUBphZyv7dURnNFyJcYWkjLjk1aX3ynx0X+PGrLtECe/Fn3wfdjSg3qA3 | ||
9g0I+ZneeXeRMidXZFnvk/YJQnAnUHTa9/raDAQoYtnNmzm+5meRo00BQR4rJuJJ | ||
Jg1+67fSSy3i6OQfFlC+eeGTyyjH9hcAwrN48TVVv6IRcljyUX1GF0YpcdfpQXK6 | ||
S7JCDSrwzTJeifcBN/2xPvqHb0fUS4hIVtMy6KwUvaL7miKXxRJE6BFAQ1nhQCUQ | ||
P+DBSNmnAgMBAAECggEAAviCnyLtVgxBhJbGesWaEvVL4QEnGJ+jKu9aTmhNM4HX | ||
1xq+54glIWxm0tW90HFWIgOGohRuOBPbhDmuF1/dU619mmmUMkfazCU9NOf7eZPB | ||
dtwEaA+AWssUkMl4bLUlurz0hu1Kc58NsmH+bGIWy266q0Ps1zqKsTkbeu7IGzDK | ||
zFJ/HoJvdNuNYdvaHH8ofvW9oDEiC2plfpNRMj13NLmXDZyXjY08654LRN5DogID | ||
K6NjEEB7gyjzDcusu+2Y0S9YMtuDiJkhlyl1lpF9FKAvaGKP7Wn6M02Oksu6UlVO | ||
kaMmAYighegY6JSGrtm+ppggGwoWgvfFCniAd8qicQKBgQDRvRCJnqPuo5CwWrEc | ||
jalNS/YhJPfZJuFfJsWUsb2ynY/0We4ZtwLgpjBcxxPnExW/4RFEnZJ8Ro45e+bt | ||
dpbVVQGXEz9GzwwqWnSJF0UOloSDRmmTmdKxaO3zaaRKbM9Oa3FkFC+hALN0g0Nz | ||
l84encxgjuq3gPdlwFRzOBqp/QKBgQDjcR+WV/AQCtCEibON9YSilpbrKd8pjjzu | ||
CnRcHPrRVLSmM4qElag8M3bJ0LFeaGcKtNC9F3A/u82BGuo91ZzXOdRmoJoZVV5I | ||
vCRnDIKrYtLAE7HaJG2qV//bPm+n80PaTind7m3Sy5fcf0BLL3rOjsMcVJEgi+LR | ||
YnODmh6BcwKBgQC8J9lzLE8yYagGnYWv8OIGBvRKLajvNTMPsm+kAoQEfddLxXWV | ||
uhmpwU03nhybuwJS/a0JGjb0qDMlHKNBOpb70OO5TToB4vKt+DH9XlPET4GXZw6F | ||
rIRYRaLaMFaDsfOUDU1PE9Dapg9Xof5b776otrVHlk64ysimjpD0QEujXQKBgQDj | ||
U84elwZ7AlQoJPoyiZNobtupcNB82I5N3mUvLEgFsoRdGmb43hypD0dLsCuYEQHs | ||
0Y1RcnvfN/bPc/dslnWNKWACs8NSTuFOEb7QwNBaPQwor4a0YnS6LfqtSFqRo7PO | ||
HxH5oLZkWtoOqaG5hFta2ZZqWpwzy52Jar3Ka+DRwQKBgG8MRvHJzbGJiTzgn1O8 | ||
1e4Xb8rJMVwki0LoWJPEUZkXvjjpNKp6OkEYpNEQADM0mPBwOX0hWFADglX/nMVT | ||
s//bCl+S0jOwugVBfDfJIJf9n+QhEI3mdKxywx2vCNklEDEcvnUuSIeWrY5/E8af | ||
z8t9XRIHIeixrlNbTWFQGVv8 | ||
-----END PRIVATE KEY----- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.