AWS-Signature-V4

 view release on metacpan or  search on metacpan

README  view on Meta::CPAN

 The chunker

    When streaming, "sign" returns a chunker that wraps the data into
    chunks, signing them if needed. It keeps track of the amount of data
    and of the signatures, so use it for one body only, and feed it the
    data in order.

  chunk

       my $encoded = $chunker->chunk($data);

    Return the encoded version of a piece of data, to be sent as it is.
    $data is a byte string or a reference to one, it cannot be empty. It is
    an error to go past the decoded_content_length.

  finish

       my $encoded = $chunker->finish(%trailer_values);

    Return the final, empty chunk, followed by the trailers if any. It is
    an error if the amount of data is not decoded_content_length. The
    values of the trailers declared in trailers are passed by name, in any
    case; it is an error to omit one, to pass one twice, to pass one that
    was not declared or that is computed by the chunker, or to pass a value
    that is not a byte string or has a CR, LF or NUL in it. After an error,
    the chunker is as it was: finish can be called again.

ERRORS

    Errors are reported by throwing Ouch exceptions (see $@->code,
    $@->message). The code is 400 when the problem is in what the caller
    provided, e.g. a missing option, an invalid URL, a certificate that
    cannot be read, a chunk that goes past the declared size; it is 500
    when the fault is in the module itself, i.e. something that should not
    happen whatever the input. The exception is reported at the line of the
    caller, and its trace does not include the arguments of the calls, as
    they may hold secrets like passwords. Moo's own complaints, e.g. about
    the arguments of the constructors that are not meant to be called
    directly, are not Ouch exceptions.

SECURITY CONSIDERATIONS

      * URLs. A URL must be ASCII, without control characters and without
      user information (user@host): AWS endpoints never have it, and user
      agents do not all agree on which host such a URL points to. For the
      same reason the host can only be a name made of letters, digits, .,
      _, ~ and -, or an IP address, with an optional numeric port.

      * Authorize on what is signed. For every service but S3 the path is
      normalized before signing, as AWS does: /public/../admin/delete is
      signed as /admin/delete, and that is what AWS executes. If your
      application decides whether a caller may have a request signed by
      looking at the URL, it must look at the normalized path (see the
      second line of canonical_request), not at the raw URL, or it can be
      bypassed. For those same services, dot segments that are
      percent-encoded (e.g. %2e%2e) are an error, as it is not certain how
      AWS reads them; S3 does not normalize at all, so there they are
      ordinary characters of the key and /public/%2e%2e/admin is signed as
      it is.

      * Do not log the results. headers and authorization can be used to
      replay the request for up to 15 minutes; a presigned URL is a bearer
      token until it expires; headers, canonical_request and presigned URLs
      include the session token, if there is one. Treat them as secrets.

      * Secrets in memory. The signer keeps the credentials (the secret
      access key included) as long as it lives, and ->credentials gives
      them back. The text of an X.509 private key and its password are
      dropped once the key is loaded. The key derived for signed chunks,
      which could sign any request for the same service, region and day, is
      kept by the chunker in a closure: no accessor gives back its bytes
      and dumping the chunker does not show them, but whoever holds the
      chunker can still sign with it through its internals. Do not hand the
      chunker, let alone the signer, to code that you would not trust with
      the credentials.

      * Error messages may include values that the caller provided, with
      non-printable characters escaped (e.g. \x{A}), so that they cannot
      forge lines in a log.

      * Dependencies are listed with their versions in cpanfile.snapshot;
      check them regularly against published advisories, e.g. with
      CPAN::Audit.

BUGS AND LIMITATIONS

    Minimum perl version 5.24.

    Only Signature Version 4 is supported, not Version 4A (asymmetric,
    multi-region). Event stream signing is not supported either.

    Signing with the X.509 variant, including presigned URLs and the
    transport of the certificate in the query string, follows the algorithm
    as documented for IAM Roles Anywhere but has only been tested with
    local signatures.

    The signature of trailers in streaming uploads has not been checked
    against AWS.

    Please report any bug or feature request through the repository of the
    project, available at https://codeberg.org/polettix/AWS-Signature-V4.

AUTHOR

    Flavio Poletti <flavio@polettix.it>

AI ASSISTANCE

    This module was developed with the assistance of artificial
    intelligence (Anthropic Claude 5). The AI was used to generate the code
    based on the specifications from Amazon and directions from the author
    to organize the code and use relevant base modules.

    All AI-generated code has been manually audited, refactored, and
    verified by the maintainer to ensure compliance with Perl best
    practices and security standards.

COPYRIGHT AND LICENSE

    Copyright 2026 by Flavio Poletti <flavio@polettix.it>

    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.



( run in 0.556 second using v1.01-cache-2.11-cpan-eca53f54451 )