96 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			96 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Go
		
	
	
	
// Modified by 42wim
 | 
						|
//
 | 
						|
// Copyright 2021 The Sigstore Authors.
 | 
						|
//
 | 
						|
// 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 sshsig
 | 
						|
 | 
						|
import (
 | 
						|
	"errors"
 | 
						|
	"fmt"
 | 
						|
 | 
						|
	"github.com/42wim/sshsig/pem"
 | 
						|
 | 
						|
	"golang.org/x/crypto/ssh"
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	pemType = "SSH SIGNATURE"
 | 
						|
)
 | 
						|
 | 
						|
// Armored returns the signature in an armored format.
 | 
						|
func Armor(s *ssh.Signature, p ssh.PublicKey, ns string) []byte {
 | 
						|
	sig := WrappedSig{
 | 
						|
		Version:       1,
 | 
						|
		PublicKey:     string(p.Marshal()),
 | 
						|
		Namespace:     ns,
 | 
						|
		HashAlgorithm: defaultHashAlgorithm,
 | 
						|
		Signature:     string(ssh.Marshal(s)),
 | 
						|
	}
 | 
						|
 | 
						|
	copy(sig.MagicHeader[:], magicHeader)
 | 
						|
 | 
						|
	enc := pem.EncodeToMemory(&pem.Block{
 | 
						|
		Type:  pemType,
 | 
						|
		Bytes: ssh.Marshal(sig),
 | 
						|
	})
 | 
						|
	return enc
 | 
						|
}
 | 
						|
 | 
						|
// Decode parses an armored signature.
 | 
						|
func Decode(b []byte) (*Signature, error) {
 | 
						|
	pemBlock, _ := pem.Decode(b)
 | 
						|
	if pemBlock == nil {
 | 
						|
		return nil, errors.New("unable to decode pem file")
 | 
						|
	}
 | 
						|
 | 
						|
	if pemBlock.Type != pemType {
 | 
						|
		return nil, fmt.Errorf("wrong pem block type: %s. Expected SSH-SIGNATURE", pemBlock.Type)
 | 
						|
	}
 | 
						|
 | 
						|
	// Now we unmarshal it into the Signature block
 | 
						|
	sig := WrappedSig{}
 | 
						|
	if err := ssh.Unmarshal(pemBlock.Bytes, &sig); err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	if sig.Version != 1 {
 | 
						|
		return nil, fmt.Errorf("unsupported signature version: %d", sig.Version)
 | 
						|
	}
 | 
						|
	if string(sig.MagicHeader[:]) != magicHeader {
 | 
						|
		return nil, fmt.Errorf("invalid magic header: %s", sig.MagicHeader[:])
 | 
						|
	}
 | 
						|
	if _, ok := supportedHashAlgorithms[sig.HashAlgorithm]; !ok {
 | 
						|
		return nil, fmt.Errorf("unsupported hash algorithm: %s", sig.HashAlgorithm)
 | 
						|
	}
 | 
						|
 | 
						|
	// Now we can unpack the Signature and PublicKey blocks
 | 
						|
	sshSig := ssh.Signature{}
 | 
						|
	if err := ssh.Unmarshal([]byte(sig.Signature), &sshSig); err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	// TODO: check the format here (should be rsa-sha512)
 | 
						|
 | 
						|
	pk, err := ssh.ParsePublicKey([]byte(sig.PublicKey))
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	return &Signature{
 | 
						|
		signature: &sshSig,
 | 
						|
		pk:        pk,
 | 
						|
		hashAlg:   sig.HashAlgorithm,
 | 
						|
	}, nil
 | 
						|
}
 |