Added oid which is a fork of https://github.com/mastahyeti/cms/tree/master/oid; contains the needed OIDs for cryptographic message syntax.
This commit is contained in:
		
							
								
								
									
										129
									
								
								oid/oid.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								oid/oid.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,129 @@ | ||||
| // Package oid contains OIDs that are used by other packages in this repository. | ||||
| package oid | ||||
|  | ||||
| import ( | ||||
| 	"crypto" | ||||
| 	"crypto/x509" | ||||
| 	"crypto/x509/pkix" | ||||
| 	"encoding/asn1" | ||||
| ) | ||||
|  | ||||
| // Content type OIDs | ||||
| var ( | ||||
| 	Data               = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 1} | ||||
| 	SignedData         = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 2} | ||||
| 	EnvelopedData      = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 3} | ||||
| 	AuthEnvelopedData  = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 16, 1, 23} | ||||
| 	TSTInfo            = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 16, 1, 4} | ||||
| 	ContentTypeTSTInfo = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 16, 1, 4} | ||||
| ) | ||||
|  | ||||
| // Attribute OIDs | ||||
| var ( | ||||
| 	AttributeContentType    = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 3} | ||||
| 	AttributeMessageDigest  = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 4} | ||||
| 	AttributeSigningTime    = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 5} | ||||
| 	AttributeTimeStampToken = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 16, 2, 14} | ||||
| ) | ||||
|  | ||||
| // Signature Algorithm  OIDs | ||||
| var ( | ||||
| 	SignatureAlgorithmRSA   = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1} | ||||
| 	SignatureAlgorithmECDSA = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1} | ||||
| ) | ||||
|  | ||||
| // Public Key Encryption OIDs | ||||
| var ( | ||||
| 	EncryptionAlgorithmRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1} | ||||
| ) | ||||
|  | ||||
| // Digest Algorithm OIDs | ||||
| var ( | ||||
| 	DigestAlgorithmSHA1   = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 26} | ||||
| 	DigestAlgorithmMD5    = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 5} | ||||
| 	DigestAlgorithmSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 1} | ||||
| 	DigestAlgorithmSHA384 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 2} | ||||
| 	DigestAlgorithmSHA512 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 3} | ||||
| ) | ||||
|  | ||||
| // X.509 extensions | ||||
| var ( | ||||
| 	SubjectKeyIdentifier = asn1.ObjectIdentifier{2, 5, 29, 14} | ||||
| ) | ||||
|  | ||||
| // DigestAlgorithmToHash maps digest OIDs to crypto.Hash values. | ||||
| var DigestAlgorithmToHash = map[string]crypto.Hash{ | ||||
| 	DigestAlgorithmSHA1.String():   crypto.SHA1, | ||||
| 	DigestAlgorithmMD5.String():    crypto.MD5, | ||||
| 	DigestAlgorithmSHA256.String(): crypto.SHA256, | ||||
| 	DigestAlgorithmSHA384.String(): crypto.SHA384, | ||||
| 	DigestAlgorithmSHA512.String(): crypto.SHA512, | ||||
| } | ||||
|  | ||||
| // HashToDigestAlgorithm maps crypto.Hash values to digest OIDs. | ||||
| var HashToDigestAlgorithm = map[crypto.Hash]asn1.ObjectIdentifier{ | ||||
| 	crypto.SHA1:   DigestAlgorithmSHA1, | ||||
| 	crypto.MD5:    DigestAlgorithmMD5, | ||||
| 	crypto.SHA256: DigestAlgorithmSHA256, | ||||
| 	crypto.SHA384: DigestAlgorithmSHA384, | ||||
| 	crypto.SHA512: DigestAlgorithmSHA512, | ||||
| } | ||||
|  | ||||
| // SignatureAlgorithmToDigestAlgorithm maps x509.SignatureAlgorithm to | ||||
| // digestAlgorithm OIDs. | ||||
| var SignatureAlgorithmToDigestAlgorithm = map[x509.SignatureAlgorithm]asn1.ObjectIdentifier{ | ||||
| 	x509.SHA1WithRSA:     DigestAlgorithmSHA1, | ||||
| 	x509.MD5WithRSA:      DigestAlgorithmMD5, | ||||
| 	x509.SHA256WithRSA:   DigestAlgorithmSHA256, | ||||
| 	x509.SHA384WithRSA:   DigestAlgorithmSHA384, | ||||
| 	x509.SHA512WithRSA:   DigestAlgorithmSHA512, | ||||
| 	x509.ECDSAWithSHA1:   DigestAlgorithmSHA1, | ||||
| 	x509.ECDSAWithSHA256: DigestAlgorithmSHA256, | ||||
| 	x509.ECDSAWithSHA384: DigestAlgorithmSHA384, | ||||
| 	x509.ECDSAWithSHA512: DigestAlgorithmSHA512, | ||||
| } | ||||
|  | ||||
| // SignatureAlgorithmToSignatureAlgorithm maps x509.SignatureAlgorithm to | ||||
| // signatureAlgorithm OIDs. | ||||
| var SignatureAlgorithmToSignatureAlgorithm = map[x509.SignatureAlgorithm]asn1.ObjectIdentifier{ | ||||
| 	x509.SHA1WithRSA:     SignatureAlgorithmRSA, | ||||
| 	x509.MD5WithRSA:      SignatureAlgorithmRSA, | ||||
| 	x509.SHA256WithRSA:   SignatureAlgorithmRSA, | ||||
| 	x509.SHA384WithRSA:   SignatureAlgorithmRSA, | ||||
| 	x509.SHA512WithRSA:   SignatureAlgorithmRSA, | ||||
| 	x509.ECDSAWithSHA1:   SignatureAlgorithmECDSA, | ||||
| 	x509.ECDSAWithSHA256: SignatureAlgorithmECDSA, | ||||
| 	x509.ECDSAWithSHA384: SignatureAlgorithmECDSA, | ||||
| 	x509.ECDSAWithSHA512: SignatureAlgorithmECDSA, | ||||
| } | ||||
|  | ||||
| // SignatureAlgorithms maps digest and signature OIDs to | ||||
| // x509.SignatureAlgorithm values. | ||||
| var SignatureAlgorithms = map[string]map[string]x509.SignatureAlgorithm{ | ||||
| 	SignatureAlgorithmRSA.String(): map[string]x509.SignatureAlgorithm{ | ||||
| 		DigestAlgorithmSHA1.String():   x509.SHA1WithRSA, | ||||
| 		DigestAlgorithmMD5.String():    x509.MD5WithRSA, | ||||
| 		DigestAlgorithmSHA256.String(): x509.SHA256WithRSA, | ||||
| 		DigestAlgorithmSHA384.String(): x509.SHA384WithRSA, | ||||
| 		DigestAlgorithmSHA512.String(): x509.SHA512WithRSA, | ||||
| 	}, | ||||
| 	SignatureAlgorithmECDSA.String(): map[string]x509.SignatureAlgorithm{ | ||||
| 		DigestAlgorithmSHA1.String():   x509.ECDSAWithSHA1, | ||||
| 		DigestAlgorithmSHA256.String(): x509.ECDSAWithSHA256, | ||||
| 		DigestAlgorithmSHA384.String(): x509.ECDSAWithSHA384, | ||||
| 		DigestAlgorithmSHA512.String(): x509.ECDSAWithSHA512, | ||||
| 	}, | ||||
| } | ||||
|  | ||||
| // PublicKeyAlgorithmToSignatureAlgorithm maps certificate public key | ||||
| // algorithms to CMS signature algorithms. | ||||
| var PublicKeyAlgorithmToSignatureAlgorithm = map[x509.PublicKeyAlgorithm]pkix.AlgorithmIdentifier{ | ||||
| 	x509.RSA:   pkix.AlgorithmIdentifier{Algorithm: SignatureAlgorithmRSA}, | ||||
| 	x509.ECDSA: pkix.AlgorithmIdentifier{Algorithm: SignatureAlgorithmECDSA}, | ||||
| } | ||||
|  | ||||
| // PublicKeyAlgorithmToEncrytionAlgorithm maps certificate public key | ||||
| // algorithms to CMS encryption algorithms. | ||||
| var PublicKeyAlgorithmToEncrytionAlgorithm = map[x509.PublicKeyAlgorithm]pkix.AlgorithmIdentifier{ | ||||
| 	x509.RSA: pkix.AlgorithmIdentifier{Algorithm: EncryptionAlgorithmRSA}, | ||||
| } | ||||
							
								
								
									
										260
									
								
								oid/symmetric_ciphers.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										260
									
								
								oid/symmetric_ciphers.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,260 @@ | ||||
| package oid | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"crypto/aes" | ||||
| 	"crypto/cipher" | ||||
| 	"crypto/des" | ||||
| 	"crypto/rand" | ||||
| 	"crypto/x509/pkix" | ||||
| 	"encoding/asn1" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
|  | ||||
| 	"golang.org/x/crypto/chacha20poly1305" | ||||
| ) | ||||
|  | ||||
| // EncryptionAlgorithm does the handling of the encrypton and decryption for a given algorithm identifier. | ||||
| type EncryptionAlgorithm struct { | ||||
| 	EncryptionAlgorithmIdentifier        asn1.ObjectIdentifier | ||||
| 	ContentEncryptionAlgorithmIdentifier pkix.AlgorithmIdentifier | ||||
| 	Key, IV, MAC                         []byte | ||||
| } | ||||
|  | ||||
| // Encryption Algorithm OIDs | ||||
| var ( | ||||
| 	EncryptionAlgorithmDESCBC     = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 7} | ||||
| 	EncryptionAlgorithmDESEDE3CBC = asn1.ObjectIdentifier{1, 2, 840, 113549, 3, 7} | ||||
| 	EncryptionAlgorithmAES128CBC  = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 2} | ||||
| 	EncryptionAlgorithmAES256CBC  = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 42} | ||||
| 	//AEAD | ||||
| 	EncryptionAlgorithmAES128GCM = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 6} | ||||
| 	AEADChaCha20Poly1305         = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 16, 3, 18} | ||||
| ) | ||||
|  | ||||
| var symmetricKeyLen = map[string]int{ | ||||
| 	EncryptionAlgorithmDESCBC.String():     7, | ||||
| 	EncryptionAlgorithmDESEDE3CBC.String(): 21, | ||||
| 	EncryptionAlgorithmAES128CBC.String():  16, | ||||
| 	EncryptionAlgorithmAES256CBC.String():  32, | ||||
| 	//AEAD | ||||
| 	EncryptionAlgorithmAES128GCM.String(): 16, | ||||
| 	AEADChaCha20Poly1305.String():         32, | ||||
| } | ||||
|  | ||||
| // Encrypt encrypts the plaintext and returns the ciphertext. | ||||
| func (e *EncryptionAlgorithm) Encrypt(plaintext []byte) (ciphertext []byte, err error) { | ||||
|  | ||||
| 	if e.Key == nil { | ||||
| 		e.Key = make([]byte, symmetricKeyLen[e.EncryptionAlgorithmIdentifier.String()]) | ||||
| 		rand.Read(e.Key) | ||||
| 	} | ||||
|  | ||||
| 	//Choose cipher | ||||
| 	var blockCipher cipher.Block | ||||
|  | ||||
| 	switch e.EncryptionAlgorithmIdentifier.String() { | ||||
| 	case EncryptionAlgorithmAES128CBC.String(), EncryptionAlgorithmAES256CBC.String(), EncryptionAlgorithmAES128GCM.String(): | ||||
| 		blockCipher, err = aes.NewCipher(e.Key) | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 	case AEADChaCha20Poly1305.String(): | ||||
| 	default: | ||||
| 		err = errors.New("Content encrytion: cipher not supportet") | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	//Choose blockmode | ||||
| 	var blockMode cipher.BlockMode | ||||
| 	var aead cipher.AEAD | ||||
| 	switch e.EncryptionAlgorithmIdentifier.String() { | ||||
| 	case EncryptionAlgorithmAES128CBC.String(), EncryptionAlgorithmAES256CBC.String(): | ||||
| 		if e.IV == nil { | ||||
| 			e.IV = make([]byte, len(e.Key)) | ||||
| 			rand.Read(e.IV) | ||||
| 		} | ||||
|  | ||||
| 		blockMode = cipher.NewCBCEncrypter(blockCipher, e.IV) | ||||
| 		e.ContentEncryptionAlgorithmIdentifier = pkix.AlgorithmIdentifier{ | ||||
| 			Algorithm:  e.EncryptionAlgorithmIdentifier, | ||||
| 			Parameters: asn1.RawValue{Tag: 4, Bytes: e.IV}} | ||||
| 	case EncryptionAlgorithmAES128GCM.String(): | ||||
| 		aead, err = cipher.NewGCM(blockCipher) | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 	case AEADChaCha20Poly1305.String(): | ||||
| 		aead, err = chacha20poly1305.New(e.Key) | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	switch e.EncryptionAlgorithmIdentifier.String() { | ||||
| 	case EncryptionAlgorithmAES128CBC.String(), EncryptionAlgorithmAES256CBC.String(): | ||||
| 		var plain []byte | ||||
| 		plain, err = pad(plaintext, blockCipher.BlockSize()) | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		ciphertext = make([]byte, len(plain)) | ||||
|  | ||||
| 		blockMode.CryptBlocks(ciphertext, plain) | ||||
|  | ||||
| 		return | ||||
| 	case EncryptionAlgorithmAES128GCM.String(), AEADChaCha20Poly1305.String(): | ||||
| 		nonce := make([]byte, nonceSize) | ||||
| 		_, err = rand.Read(nonce) | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		ciphertext = aead.Seal(nil, nonce, plaintext, nil) | ||||
|  | ||||
| 		e.MAC = ciphertext[len(ciphertext)-aead.Overhead():] | ||||
| 		ciphertext = ciphertext[:len(ciphertext)-aead.Overhead()] | ||||
| 		switch e.EncryptionAlgorithmIdentifier.String() { | ||||
| 		case EncryptionAlgorithmAES128GCM.String(): | ||||
| 			paramSeq := aesGCMParameters{ | ||||
| 				Nonce:  nonce, | ||||
| 				ICVLen: aead.Overhead(), | ||||
| 			} | ||||
|  | ||||
| 			paramBytes, _ := asn1.Marshal(paramSeq) | ||||
|  | ||||
| 			e.ContentEncryptionAlgorithmIdentifier = pkix.AlgorithmIdentifier{ | ||||
| 				Algorithm: e.EncryptionAlgorithmIdentifier, | ||||
| 				Parameters: asn1.RawValue{ | ||||
| 					Tag:   asn1.TagSequence, | ||||
| 					Bytes: paramBytes, | ||||
| 				}} | ||||
| 		case AEADChaCha20Poly1305.String(): | ||||
| 			e.ContentEncryptionAlgorithmIdentifier = pkix.AlgorithmIdentifier{ | ||||
| 				Algorithm:  e.EncryptionAlgorithmIdentifier, | ||||
| 				Parameters: asn1.RawValue{Tag: 4, Bytes: nonce}} | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| const nonceSize = 12 | ||||
|  | ||||
| type aesGCMParameters struct { | ||||
| 	Nonce  []byte `asn1:"tag:4"` | ||||
| 	ICVLen int | ||||
| } | ||||
|  | ||||
| // Decrypt decrypts the ciphertext and returns the plaintext. | ||||
| func (e *EncryptionAlgorithm) Decrypt(ciphertext []byte) (plaintext []byte, err error) { | ||||
|  | ||||
| 	e.EncryptionAlgorithmIdentifier = e.ContentEncryptionAlgorithmIdentifier.Algorithm | ||||
|  | ||||
| 	//Choose cipher | ||||
| 	var blockCipher cipher.Block | ||||
|  | ||||
| 	switch e.EncryptionAlgorithmIdentifier.String() { | ||||
| 	case EncryptionAlgorithmAES128CBC.String(), EncryptionAlgorithmAES256CBC.String(), EncryptionAlgorithmAES128GCM.String(): | ||||
| 		blockCipher, err = aes.NewCipher(e.Key) | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 	case EncryptionAlgorithmDESCBC.String(): | ||||
| 		blockCipher, err = des.NewCipher(e.Key) | ||||
| 		fmt.Println("Warning: message is encoded with DES. DES should NOT be used.") | ||||
| 	case EncryptionAlgorithmDESEDE3CBC.String(): | ||||
| 		blockCipher, err = des.NewTripleDESCipher(e.Key) | ||||
| 		fmt.Println("Warning: message is encoded with 3DES. 3DES should NOT be used.") | ||||
| 	case AEADChaCha20Poly1305.String(): | ||||
| 	default: | ||||
| 		err = errors.New("Content encrytion: cipher not supportet") | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	//Choose blockmode | ||||
| 	var blockMode cipher.BlockMode | ||||
| 	var aead cipher.AEAD | ||||
| 	switch e.EncryptionAlgorithmIdentifier.String() { | ||||
| 	case EncryptionAlgorithmAES128CBC.String(), EncryptionAlgorithmAES256CBC.String(), EncryptionAlgorithmDESCBC.String(), EncryptionAlgorithmDESEDE3CBC.String(): | ||||
| 		e.IV = e.ContentEncryptionAlgorithmIdentifier.Parameters.Bytes | ||||
|  | ||||
| 		blockMode = cipher.NewCBCDecrypter(blockCipher, e.IV) | ||||
| 	case EncryptionAlgorithmAES128GCM.String(): | ||||
| 		aead, err = cipher.NewGCM(blockCipher) | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 	case AEADChaCha20Poly1305.String(): | ||||
| 		aead, err = chacha20poly1305.New(e.Key) | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	switch e.EncryptionAlgorithmIdentifier.String() { | ||||
| 	case EncryptionAlgorithmAES128CBC.String(), EncryptionAlgorithmAES256CBC.String(), EncryptionAlgorithmDESCBC.String(), EncryptionAlgorithmDESEDE3CBC.String(): | ||||
| 		plaintext = make([]byte, len(ciphertext)) | ||||
| 		blockMode.CryptBlocks(plaintext, ciphertext) | ||||
|  | ||||
| 		return unpad(plaintext, blockMode.BlockSize()) | ||||
| 	case EncryptionAlgorithmAES128GCM.String(), AEADChaCha20Poly1305.String(): | ||||
| 		var cipher []byte | ||||
| 		cipher = append(cipher, ciphertext...) | ||||
| 		cipher = append(cipher, e.MAC...) | ||||
|  | ||||
| 		var nonce []byte | ||||
| 		switch e.EncryptionAlgorithmIdentifier.String() { | ||||
| 		case EncryptionAlgorithmAES128GCM.String(): | ||||
| 			params := aesGCMParameters{} | ||||
| 			paramBytes := e.ContentEncryptionAlgorithmIdentifier.Parameters.Bytes | ||||
| 			_, err = asn1.Unmarshal(paramBytes, ¶ms) | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 			nonce = params.Nonce | ||||
| 		case AEADChaCha20Poly1305.String(): | ||||
| 			nonce = e.ContentEncryptionAlgorithmIdentifier.Parameters.Bytes | ||||
| 		} | ||||
|  | ||||
| 		plaintext, err = aead.Open(nil, nonce, cipher, nil) | ||||
| 		return | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func pad(data []byte, blocklen int) ([]byte, error) { | ||||
| 	if blocklen < 1 { | ||||
| 		return nil, fmt.Errorf("invalid blocklen %d", blocklen) | ||||
| 	} | ||||
| 	padlen := blocklen - (len(data) % blocklen) | ||||
| 	if padlen == 0 { | ||||
| 		padlen = blocklen | ||||
| 	} | ||||
| 	pad := bytes.Repeat([]byte{byte(padlen)}, padlen) | ||||
| 	return append(data, pad...), nil | ||||
| } | ||||
|  | ||||
| func unpad(data []byte, blocklen int) ([]byte, error) { | ||||
| 	if blocklen < 1 { | ||||
| 		return nil, fmt.Errorf("invalid blocklen %d", blocklen) | ||||
| 	} | ||||
| 	if len(data)%blocklen != 0 || len(data) == 0 { | ||||
| 		return nil, fmt.Errorf("invalid data len %d", len(data)) | ||||
| 	} | ||||
|  | ||||
| 	// the last byte is the length of padding | ||||
| 	padlen := int(data[len(data)-1]) | ||||
|  | ||||
| 	// check padding integrity, all bytes should be the same | ||||
| 	pad := data[len(data)-padlen:] | ||||
| 	for _, padbyte := range pad { | ||||
| 		if padbyte != byte(padlen) { | ||||
| 			return nil, errors.New("invalid padding") | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return data[:len(data)-padlen], nil | ||||
| } | ||||
		Reference in New Issue
	
	Block a user