carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1// SMTP credential derivation. SES's SMTP password is not issued by an API —
2// it is a deterministic function of the IAM secret access key and the
3// region, which is why this package can hand an app working SMTP
4// credentials without a second AWS call, and why the secret itself never
5// needs to be stored anywhere (spec §3, §4).
6package mail
7
8import (
9 "crypto/hmac"
10 "crypto/sha256"
11 "encoding/base64"
12)
13
14// The four constants of AWS's published derivation. smtpDate is a literal
15// "11111111" and NOT today's date — SES fixed it so the password does not
16// expire; using a real date silently produces a credential SES rejects.
17const (
18 smtpDate = "11111111"
19 smtpService = "ses"
20 smtpTerminal = "aws4_request"
21 smtpMessage = "SendRawEmail"
22 smtpVersion = 0x04
23)
24
25func hmac256(key []byte, data string) []byte {
26 h := hmac.New(sha256.New, key)
27 h.Write([]byte(data))
28 return h.Sum(nil)
29}
30
31// SMTPPassword derives the SES SMTP password for an IAM secret access key
32// in region. The matching SMTP username is the access key ID, unmodified.
33//
34// The signing chain is date → region → service → terminal → message, seeded
35// with "AWS4"+secret, and the result is the version byte followed by the
36// HMAC. Every step is load-bearing and the order is not negotiable.
37func SMTPPassword(secretKey, region string) string {
38 sig := []byte("AWS4" + secretKey)
39 for _, step := range []string{smtpDate, region, smtpService, smtpTerminal, smtpMessage} {
40 sig = hmac256(sig, step)
41 }
42 return base64.StdEncoding.EncodeToString(append([]byte{smtpVersion}, sig...))
43}
44