github.com/egonelbre/exp@v0.0.0-20240430123955-ed1d3aa93911/smime/parse.go (about) 1 package smime 2 3 import ( 4 "bytes" 5 "encoding/asn1" 6 "fmt" 7 8 "github.com/egonelbre/exp/smime/ber" 9 ) 10 11 // RFC 5652 12.1 12 // -- Content Type Object Identifiers 13 // 14 // id-ct-contentInfo OBJECT IDENTIFIER ::= { iso(1) member-body(2) 15 // us(840) rsadsi(113549) pkcs(1) pkcs9(9) smime(16) ct(1) 6 } 16 // 17 // id-data OBJECT IDENTIFIER ::= { iso(1) member-body(2) 18 // us(840) rsadsi(113549) pkcs(1) pkcs7(7) 1 } 19 // 20 // id-signedData OBJECT IDENTIFIER ::= { iso(1) member-body(2) 21 // us(840) rsadsi(113549) pkcs(1) pkcs7(7) 2 } 22 // 23 // id-envelopedData OBJECT IDENTIFIER ::= { iso(1) member-body(2) 24 // us(840) rsadsi(113549) pkcs(1) pkcs7(7) 3 } 25 // 26 // id-digestedData OBJECT IDENTIFIER ::= { iso(1) member-body(2) 27 // us(840) rsadsi(113549) pkcs(1) pkcs7(7) 5 } 28 // 29 // id-encryptedData OBJECT IDENTIFIER ::= { iso(1) member-body(2) 30 // us(840) rsadsi(113549) pkcs(1) pkcs7(7) 6 } 31 // 32 // id-ct-authData OBJECT IDENTIFIER ::= { iso(1) member-body(2) 33 // us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) ct(1) 2 } 34 var ( 35 oidContentInfo = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 16, 1, 6} 36 37 oidData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 1} 38 oidSignedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 2} 39 oidEnvelopedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 3} 40 oidDigestedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 5} 41 oidEncryptedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 6} 42 oidAuthData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 16, 1, 2} 43 ) 44 45 type Data []byte 46 47 func Parse(data []byte) (ret interface{}, err error) { 48 d := ber.NewDecoder(bytes.NewReader(data)) 49 tree, err := ber.ParseTree(d) 50 if err != nil { 51 return nil, err 52 } 53 54 //pp(tree) 55 56 // RFC 5652, 3 57 // ContentInfo ::= SEQUENCE { 58 // contentType ContentType, 59 // content [0] EXPLICIT ANY DEFINED BY contentType } 60 // 61 // ContentType ::= OBJECT IDENTIFIER 62 63 var contentType asn1.ObjectIdentifier 64 var content *ber.Tree 65 66 err = ber.Sequence{ 67 ber.Check{ber.Universal, ber.TagObjectIdentifier, ber.ObjectIdentifier{&contentType}}, 68 ber.Check{ber.Context, 0, ber.Explicit{ber.RawTree{&content}}}, 69 }.Unmarshal(tree) 70 if err != nil { 71 return 72 } 73 74 switch { 75 case oidData.Equal(contentType): 76 bytes, err := content.AsOctetString() 77 return Data(bytes), err 78 case oidSignedData.Equal(contentType): 79 ret, err := parseSignedData(content) 80 return ret, err 81 case oidEnvelopedData.Equal(contentType): 82 return nil, fmt.Errorf("enveloped-data not suppoerted") 83 case oidDigestedData.Equal(contentType): 84 return nil, fmt.Errorf("digested-data not supported") 85 case oidEncryptedData.Equal(contentType): 86 return nil, fmt.Errorf("encrypted-data not supported") 87 case oidAuthData.Equal(contentType): 88 return nil, fmt.Errorf("auth-data not supported") 89 } 90 return nil, fmt.Errorf("unknown content type") 91 }