1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
|
package storageops
import (
"crypto"
"crypto/ecdsa"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"fmt"
"github.com/hlandau/acmetool/storage"
"time"
)
type targetSorter []*storage.Target
func (ts targetSorter) Len() int {
return len(ts)
}
func (ts targetSorter) Swap(i, j int) {
ts[i], ts[j] = ts[j], ts[i]
}
func (ts targetSorter) Less(i, j int) bool {
return targetGt(ts[j], ts[i])
}
func targetGt(a *storage.Target, b *storage.Target) bool {
if a == nil && b == nil {
return false // equal
} else if b == nil {
return true // a > nil
} else if a == nil {
return false // nil < a
}
if a.Priority > b.Priority {
return true
} else if a.Priority < b.Priority {
return false
}
return len(a.Satisfy.Names) > len(b.Satisfy.Names)
}
// This is 30 days, which is a bit high, but Let's Encrypt sends expiration
// emails at 19 days, so...
const defaultRenewalMarginDays = 30
func renewTime(notBefore, notAfter time.Time, t *storage.Target) time.Time {
renewalMarginDays := defaultRenewalMarginDays
if t.Satisfy.Margin > 0 {
renewalMarginDays = t.Satisfy.Margin
}
renewalMargin := time.Duration(renewalMarginDays) * 24 * time.Hour
validityPeriod := notAfter.Sub(notBefore)
renewSpan := validityPeriod / 3
if renewSpan > renewalMargin {
renewSpan = renewalMargin
}
return notAfter.Add(-renewSpan)
}
func signatureAlgorithmFromKey(pk crypto.PrivateKey) (x509.SignatureAlgorithm, error) {
switch pk.(type) {
case *rsa.PrivateKey:
return x509.SHA256WithRSA, nil
case *ecdsa.PrivateKey:
return x509.ECDSAWithSHA256, nil
default:
return x509.UnknownSignatureAlgorithm, fmt.Errorf("unknown key type %T", pk)
}
}
func generateKey(trk *storage.TargetRequestKey) (pk crypto.PrivateKey, err error) {
switch trk.Type {
default:
fallthrough // ...
case "", "rsa":
pk, err = rsa.GenerateKey(rand.Reader, clampRSAKeySize(trk.RSASize))
case "ecdsa":
pk, err = ecdsa.GenerateKey(getECDSACurve(trk.ECDSACurve), rand.Reader)
}
return
}
// Error associated with a specific target, for clarity of error messages.
type TargetSpecificError struct {
Target *storage.Target
Err error
}
func (tse *TargetSpecificError) Error() string {
return fmt.Sprintf("error satisfying %v: %v", tse.Target, tse.Err)
}
|