awslabs / aws-sdk-rust

AWS SDK for the Rust Programming Language
https://awslabs.github.io/aws-sdk-rust/
Apache License 2.0
2.98k stars 246 forks source link

Unable to decode Blob returned in GetPublicKeyOutput #1169

Closed ShockleyJE closed 3 months ago

ShockleyJE commented 3 months ago

Describe the bug

Problem: I am able to authenticate, authorize, and successfully send() a get_public_key() request, but cannot parse the Blob returned by the AWS API into a format that is suitable to verify locally the signature of a payload sign()'ed with the corresponding private key.

Expected Behavior

I expected to be able to parse the Blob returned by send() a get_public_key(), by either..

All of this is done with the overall expectation of being able to save the public key for offline verification

Current Behavior

    // B64 decode | Error: Invalid symbol 130, offset 1.
    let inner_decoded: Vec<u8> = base64::decode(blob.as_ref())?;
    println!("inner_decoded : {inner_decoded:?}");
    // DER decode | Error: error when decoding ASN.1 data: missing further values (at position 6)
    let cert = X509Certificate::from_der(blob)?;
    println!("{cert:#?}");

### Reproduction Steps

Example:

``` Cargo.toml
x509-certificate = "0.23.1"
aws-config = "1.2.1"
aws-sdk-kms = "1.2.1"
tokio = { version = "1.27.0", features = ["full", "macros"] }
base64 = "0.22.0"
anyhow = "1"
#[tokio::main]
async fn main() -> Result<()> {
    let kms_key_arn = "...";
    let kms_client: KmsClient = kms_client().await;

    let pub_key_output: aws_sdk_kms::operation::get_public_key::GetPublicKeyOutput = kms_client.get_public_key().key_id(kms_key_arn).send().await?;
    println!("{pub_key_output:#?}");
    let blob: Blob = pub_key_output.public_key.unwrap();

    // Comment these blocks as needed

    // B64 decode | Error: Invalid symbol 130, offset 1.
    let inner_decoded: Vec<u8> = base64::decode(blob.as_ref())?;
    println!("inner_decoded : {inner_decoded:?}");

    // DER decode | Error: error when decoding ASN.1 data: missing further values (at position 6)
    let cert = X509Certificate::from_der(blob)?;
    println!("{cert:#?}");

    // Inspect the UTF-8 (I admit, this was a stretch) | Error: invalid utf-8 sequence of 1 bytes from index 1
    let string_blob = blob.clone();
    let inner_stringied = String::from_utf8(string_blob.into_inner())?;
    println!("inner_decoded is ascii: {inner_stringied:?}");
}

Possible Solution

No response

Additional Information/Context

No response

Version

│   ├── aws-config v1.2.1
│   │   ├── aws-credential-types v1.2.0
│   │   │   ├── aws-smithy-async v1.2.1
│   │   │   ├── aws-smithy-runtime-api v1.4.0
│   │   │   │   ├── aws-smithy-async v1.2.1 (*)
│   │   │   │   ├── aws-smithy-types v1.1.8
│   │   │   ├── aws-smithy-types v1.1.8 (*)
│   │   ├── aws-runtime v1.2.0
│   │   │   ├── aws-credential-types v1.2.0 (*)
│   │   │   ├── aws-sigv4 v1.2.1
│   │   │   │   ├── aws-credential-types v1.2.0 (*)
│   │   │   │   ├── aws-smithy-http v0.60.8
│   │   │   │   │   ├── aws-smithy-runtime-api v1.4.0 (*)
│   │   │   │   │   ├── aws-smithy-types v1.1.8 (*)
│   │   │   │   ├── aws-smithy-runtime-api v1.4.0 (*)
│   │   │   │   ├── aws-smithy-types v1.1.8 (*)
│   │   │   ├── aws-smithy-async v1.2.1 (*)
│   │   │   ├── aws-smithy-http v0.60.8 (*)
│   │   │   ├── aws-smithy-runtime-api v1.4.0 (*)
│   │   │   ├── aws-smithy-types v1.1.8 (*)
│   │   │   ├── aws-types v1.2.0
│   │   │   │   ├── aws-credential-types v1.2.0 (*)
│   │   │   │   ├── aws-smithy-async v1.2.1 (*)
│   │   │   │   ├── aws-smithy-runtime-api v1.4.0 (*)
│   │   │   │   ├── aws-smithy-types v1.1.8 (*)
│   │   ├── aws-sdk-sso v1.21.0
│   │   │   ├── aws-credential-types v1.2.0 (*)
│   │   │   ├── aws-runtime v1.2.0 (*)
│   │   │   ├── aws-smithy-async v1.2.1 (*)
│   │   │   ├── aws-smithy-http v0.60.8 (*)
│   │   │   ├── aws-smithy-json v0.60.7
│   │   │   │   └── aws-smithy-types v1.1.8 (*)
│   │   │   ├── aws-smithy-runtime v1.3.1
│   │   │   │   ├── aws-smithy-async v1.2.1 (*)
│   │   │   │   ├── aws-smithy-http v0.60.8 (*)
│   │   │   │   ├── aws-smithy-runtime-api v1.4.0 (*)
│   │   │   │   ├── aws-smithy-types v1.1.8 (*)
│   │   │   ├── aws-smithy-runtime-api v1.4.0 (*)
│   │   │   ├── aws-smithy-types v1.1.8 (*)
│   │   │   ├── aws-types v1.2.0 (*)
│   │   ├── aws-sdk-ssooidc v1.21.0
│   │   │   ├── aws-credential-types v1.2.0 (*)
│   │   │   ├── aws-runtime v1.2.0 (*)
│   │   │   ├── aws-smithy-async v1.2.1 (*)
│   │   │   ├── aws-smithy-http v0.60.8 (*)
│   │   │   ├── aws-smithy-json v0.60.7 (*)
│   │   │   ├── aws-smithy-runtime v1.3.1 (*)
│   │   │   ├── aws-smithy-runtime-api v1.4.0 (*)
│   │   │   ├── aws-smithy-types v1.1.8 (*)
│   │   │   ├── aws-types v1.2.0 (*)
│   │   ├── aws-sdk-sts v1.21.0
│   │   │   ├── aws-credential-types v1.2.0 (*)
│   │   │   ├── aws-runtime v1.2.0 (*)
│   │   │   ├── aws-smithy-async v1.2.1 (*)
│   │   │   ├── aws-smithy-http v0.60.8 (*)
│   │   │   ├── aws-smithy-json v0.60.7 (*)
│   │   │   ├── aws-smithy-query v0.60.7
│   │   │   │   ├── aws-smithy-types v1.1.8 (*)
│   │   │   ├── aws-smithy-runtime v1.3.1 (*)
│   │   │   ├── aws-smithy-runtime-api v1.4.0 (*)
│   │   │   ├── aws-smithy-types v1.1.8 (*)
│   │   │   ├── aws-smithy-xml v0.60.8
│   │   │   ├── aws-types v1.2.0 (*)
│   │   ├── aws-smithy-async v1.2.1 (*)
│   │   ├── aws-smithy-http v0.60.8 (*)
│   │   ├── aws-smithy-json v0.60.7 (*)
│   │   ├── aws-smithy-runtime v1.3.1 (*)
│   │   ├── aws-smithy-runtime-api v1.4.0 (*)
│   │   ├── aws-smithy-types v1.1.8 (*)
│   │   ├── aws-types v1.2.0 (*)
│   ├── aws-sdk-kms v1.22.0
│   │   ├── aws-credential-types v1.2.0 (*)
│   │   ├── aws-runtime v1.2.0 (*)
│   │   ├── aws-smithy-async v1.2.1 (*)
│   │   ├── aws-smithy-http v0.60.8 (*)
│   │   ├── aws-smithy-json v0.60.7 (*)
│   │   ├── aws-smithy-runtime v1.3.1 (*)
│   │   ├── aws-smithy-runtime-api v1.4.0 (*)
│   │   ├── aws-smithy-types v1.1.8 (*)
│   │   ├── aws-types v1.2.0 (*)
│   ├── aws-sdk-sqs v1.21.0
│   │   ├── aws-credential-types v1.2.0 (*)
│   │   ├── aws-runtime v1.2.0 (*)
│   │   ├── aws-smithy-async v1.2.1 (*)
│   │   ├── aws-smithy-http v0.60.8 (*)
│   │   ├── aws-smithy-json v0.60.7 (*)
│   │   ├── aws-smithy-runtime v1.3.1 (*)
│   │   ├── aws-smithy-runtime-api v1.4.0 (*)
│   │   ├── aws-smithy-types v1.1.8 (*)
│   │   ├── aws-types v1.2.0 (*)
├── aws-config v1.2.1 (*)
├── aws-sdk-sqs v1.21.0 (*)
├── aws-config v1.2.1 (*)
├── aws-sdk-kms v1.22.0 (*)
├── aws-sdk-sqs v1.21.0 (*)
├── aws-config v1.2.1 (*)
├── aws-sdk-sqs v1.21.0 (*)

Environment details (OS name and version, etc.)

MacOS, Apple Silicon

Logs

Logs were included as comments in the example code.

ShockleyJE commented 3 months ago

We ended up searching GitHub globally, and were able to find references in the AWS Tough project, and work backwards from there. Using pem = 3 we are at least able to print the public key contents like so

    let key = pem::encode_config(
        &pem::Pem::new("PUBLIC_KEY".to_owned(), 
        blob.into_inner()
    ),pem::EncodeConfig::new().set_line_ending(pem::LineEnding::LF));

    println!("{key:#?}");
ShockleyJE commented 3 months ago

Was able to create an RsaPublicKey eventually with rsa = 0.9.6. Will contribute back a PR with full example

    let response: aws_sdk_kms::operation::get_public_key::GetPublicKeyOutput = kms_client.get_public_key().key_id(kms_key_arn).send().await?;
    let blob: Blob = response.public_key.expect("Expected successful response from KMS");

    let pub_key = RsaPublicKey::from_public_key_der(blob.into_inner().as_ref())?;
Velfi commented 3 months ago

@ShockleyJE Thanks for sharing your findings with everyone, that's very considerate. Make sure to submit your example PR to this repo: https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/rustv1

All the examples in this repo are copied from there.

github-actions[bot] commented 3 months ago

Comments on closed issues are hard for our team to see. If you need more assistance, please either tag a team member or open a new issue that references this one. If you wish to keep having a conversation with other community members under this issue feel free to do so.