@@ -87,123 +87,97 @@ func Decode(data []byte) (p *Block, rest []byte) {
87
87
// pemStart begins with a newline. However, at the very beginning of
88
88
// the byte array, we'll accept the start string without it.
89
89
rest = data
90
- if bytes .HasPrefix (data , pemStart [1 :]) {
91
- rest = rest [len (pemStart )- 1 : len (data )]
92
- } else if i := bytes .Index (data , pemStart ); i >= 0 {
93
- rest = rest [i + len (pemStart ) : len (data )]
94
- } else {
95
- return nil , data
96
- }
97
-
98
- typeLine , rest := getLine (rest )
99
- if ! bytes .HasSuffix (typeLine , pemEndOfLine ) {
100
- return decodeError (data , rest )
101
- }
102
- typeLine = typeLine [0 : len (typeLine )- len (pemEndOfLine )]
103
-
104
- p = & Block {
105
- Headers : make (map [string ]string ),
106
- Type : string (typeLine ),
107
- }
108
-
109
90
for {
110
- // This loop terminates because getLine's second result is
111
- // always smaller than its argument.
112
- if len (rest ) == 0 {
91
+ if bytes .HasPrefix (rest , pemStart [1 :]) {
92
+ rest = rest [len (pemStart )- 1 :]
93
+ } else if i := bytes .Index (rest , pemStart ); i >= 0 {
94
+ rest = rest [i + len (pemStart ) : len (rest )]
95
+ } else {
113
96
return nil , data
114
97
}
115
- line , next := getLine (rest )
116
98
117
- i := bytes .IndexByte (line , ':' )
118
- if i == - 1 {
119
- break
99
+ var typeLine []byte
100
+ typeLine , rest = getLine (rest )
101
+ if ! bytes .HasSuffix (typeLine , pemEndOfLine ) {
102
+ continue
120
103
}
104
+ typeLine = typeLine [0 : len (typeLine )- len (pemEndOfLine )]
121
105
122
- // TODO(agl): need to cope with values that spread across lines.
123
- key , val := line [:i ], line [i + 1 :]
124
- key = bytes .TrimSpace (key )
125
- val = bytes .TrimSpace (val )
126
- p .Headers [string (key )] = string (val )
127
- rest = next
128
- }
106
+ p = & Block {
107
+ Headers : make (map [string ]string ),
108
+ Type : string (typeLine ),
109
+ }
129
110
130
- var endIndex , endTrailerIndex int
111
+ for {
112
+ // This loop terminates because getLine's second result is
113
+ // always smaller than its argument.
114
+ if len (rest ) == 0 {
115
+ return nil , data
116
+ }
117
+ line , next := getLine (rest )
131
118
132
- // If there were no headers, the END line might occur
133
- // immediately, without a leading newline.
134
- if len (p .Headers ) == 0 && bytes .HasPrefix (rest , pemEnd [1 :]) {
135
- endIndex = 0
136
- endTrailerIndex = len (pemEnd ) - 1
137
- } else {
138
- endIndex = bytes .Index (rest , pemEnd )
139
- endTrailerIndex = endIndex + len (pemEnd )
140
- }
119
+ i := bytes .IndexByte (line , ':' )
120
+ if i == - 1 {
121
+ break
122
+ }
141
123
142
- if endIndex < 0 {
143
- return decodeError (data , rest )
144
- }
124
+ // TODO(agl): need to cope with values that spread across lines.
125
+ key , val := line [:i ], line [i + 1 :]
126
+ key = bytes .TrimSpace (key )
127
+ val = bytes .TrimSpace (val )
128
+ p .Headers [string (key )] = string (val )
129
+ rest = next
130
+ }
145
131
146
- // After the "-----" of the ending line, there should be the same type
147
- // and then a final five dashes.
148
- endTrailer := rest [endTrailerIndex :]
149
- endTrailerLen := len (typeLine ) + len (pemEndOfLine )
150
- if len (endTrailer ) < endTrailerLen {
151
- return decodeError (data , rest )
152
- }
132
+ var endIndex , endTrailerIndex int
153
133
154
- restOfEndLine := endTrailer [endTrailerLen :]
155
- endTrailer = endTrailer [:endTrailerLen ]
156
- if ! bytes .HasPrefix (endTrailer , typeLine ) ||
157
- ! bytes .HasSuffix (endTrailer , pemEndOfLine ) {
158
- return decodeError (data , rest )
159
- }
134
+ // If there were no headers, the END line might occur
135
+ // immediately, without a leading newline.
136
+ if len (p .Headers ) == 0 && bytes .HasPrefix (rest , pemEnd [1 :]) {
137
+ endIndex = 0
138
+ endTrailerIndex = len (pemEnd ) - 1
139
+ } else {
140
+ endIndex = bytes .Index (rest , pemEnd )
141
+ endTrailerIndex = endIndex + len (pemEnd )
142
+ }
160
143
161
- // The line must end with only whitespace.
162
- if s , _ := getLine (restOfEndLine ); len (s ) != 0 {
163
- return decodeError (data , rest )
164
- }
144
+ if endIndex < 0 {
145
+ continue
146
+ }
165
147
166
- base64Data := removeSpacesAndTabs (rest [:endIndex ])
167
- p .Bytes = make ([]byte , base64 .StdEncoding .DecodedLen (len (base64Data )))
168
- n , err := base64 .StdEncoding .Decode (p .Bytes , base64Data )
169
- if err != nil {
170
- return decodeError (data , rest )
171
- }
172
- p .Bytes = p .Bytes [:n ]
148
+ // After the "-----" of the ending line, there should be the same type
149
+ // and then a final five dashes.
150
+ endTrailer := rest [endTrailerIndex :]
151
+ endTrailerLen := len (typeLine ) + len (pemEndOfLine )
152
+ if len (endTrailer ) < endTrailerLen {
153
+ continue
154
+ }
155
+
156
+ restOfEndLine := endTrailer [endTrailerLen :]
157
+ endTrailer = endTrailer [:endTrailerLen ]
158
+ if ! bytes .HasPrefix (endTrailer , typeLine ) ||
159
+ ! bytes .HasSuffix (endTrailer , pemEndOfLine ) {
160
+ continue
161
+ }
173
162
174
- // the -1 is because we might have only matched pemEnd without the
175
- // leading newline if the PEM block was empty.
176
- _ , rest = getLine (rest [endIndex + len (pemEnd )- 1 :])
163
+ // The line must end with only whitespace.
164
+ if s , _ := getLine (restOfEndLine ); len (s ) != 0 {
165
+ continue
166
+ }
177
167
178
- return
179
- }
168
+ base64Data := removeSpacesAndTabs (rest [:endIndex ])
169
+ p .Bytes = make ([]byte , base64 .StdEncoding .DecodedLen (len (base64Data )))
170
+ n , err := base64 .StdEncoding .Decode (p .Bytes , base64Data )
171
+ if err != nil {
172
+ continue
173
+ }
174
+ p .Bytes = p .Bytes [:n ]
180
175
181
- func decodeError (data , rest []byte ) (* Block , []byte ) {
182
- // If we get here then we have rejected a likely looking, but
183
- // ultimately invalid PEM block. We need to start over from a new
184
- // position. We have consumed the preamble line and will have consumed
185
- // any lines which could be header lines. However, a valid preamble
186
- // line is not a valid header line, therefore we cannot have consumed
187
- // the preamble line for the any subsequent block. Thus, we will always
188
- // find any valid block, no matter what bytes precede it.
189
- //
190
- // For example, if the input is
191
- //
192
- // -----BEGIN MALFORMED BLOCK-----
193
- // junk that may look like header lines
194
- // or data lines, but no END line
195
- //
196
- // -----BEGIN ACTUAL BLOCK-----
197
- // realdata
198
- // -----END ACTUAL BLOCK-----
199
- //
200
- // we've failed to parse using the first BEGIN line
201
- // and now will try again, using the second BEGIN line.
202
- p , rest := Decode (rest )
203
- if p == nil {
204
- rest = data
176
+ // the -1 is because we might have only matched pemEnd without the
177
+ // leading newline if the PEM block was empty.
178
+ _ , rest = getLine (rest [endIndex + len (pemEnd )- 1 :])
179
+ return p , rest
205
180
}
206
- return p , rest
207
181
}
208
182
209
183
const pemLineLength = 64
0 commit comments