Skip to content

Commit 89eb7fb

Browse files
committed
added support for W3C padding (in addition to PKCS#7) in the PaddedReader object, based on DRM-Inside's #111 Pull Request (updated unit tests too)
1 parent f42972d commit 89eb7fb

File tree

3 files changed

+31
-10
lines changed

3 files changed

+31
-10
lines changed

crypto/aes_cbc.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ const (
4040
)
4141

4242
func (e cbcEncrypter) Signature() string {
43+
// W3C padding scheme, not PKCS#7 (see last parameter "insertPadLengthAll" [false] of PaddedReader constructor)
4344
return "http://www.w3.org/2001/04/xmlenc#aes256-cbc"
4445
}
4546

@@ -49,7 +50,8 @@ func (e cbcEncrypter) GenerateKey() (ContentKey, error) {
4950
}
5051

5152
func (e cbcEncrypter) Encrypt(key ContentKey, r io.Reader, w io.Writer) error {
52-
r = PaddedReader(r, aes.BlockSize) // PKCS#7
53+
54+
r = PaddedReader(r, aes.BlockSize, false)
5355

5456
block, err := aes.NewCipher(key)
5557
if err != nil {
@@ -99,7 +101,7 @@ func (c cbcEncrypter) Decrypt(key ContentKey, r io.Reader, w io.Writer) error {
99101
mode := cipher.NewCBCDecrypter(block, iv)
100102
mode.CryptBlocks(buf[aes.BlockSize:], buf[aes.BlockSize:])
101103

102-
padding := buf[len(buf)-1] // PKCS#7
104+
padding := buf[len(buf)-1] // padding length valid for both PKCS#7 and W3C schemes
103105
w.Write(buf[aes.BlockSize : len(buf)-int(padding)])
104106

105107
return nil

crypto/pad.go

+22-3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ package crypto
2727

2828
import (
2929
"io"
30+
"math/rand"
31+
"time"
3032
)
3133

3234
type paddedReader struct {
@@ -35,6 +37,7 @@ type paddedReader struct {
3537
count byte
3638
left byte
3739
done bool
40+
insertPadLengthAll bool
3841
}
3942

4043
func (r *paddedReader) Read(buf []byte) (int, error) {
@@ -73,8 +76,21 @@ func (r *paddedReader) Read(buf []byte) (int, error) {
7376

7477
func (r *paddedReader) pad(buf []byte) (i int, err error) {
7578
capacity := cap(buf)
79+
80+
src := rand.New(rand.NewSource(time.Now().UnixNano()))
81+
7682
for i = 0; capacity > 0 && r.left > 0; i++ {
77-
buf[i] = r.count
83+
84+
if (r.insertPadLengthAll) {
85+
buf[i] = r.count
86+
} else {
87+
if capacity == 1 && r.left == 1 {
88+
buf[i] = r.count
89+
} else {
90+
buf[i] = byte(src.Intn(254) + 1)
91+
}
92+
}
93+
7894
capacity--
7995
r.left--
8096
}
@@ -86,6 +102,9 @@ func (r *paddedReader) pad(buf []byte) (i int, err error) {
86102
return
87103
}
88104

89-
func PaddedReader(r io.Reader, blockSize byte) io.Reader {
90-
return &paddedReader{Reader: r, size: blockSize, count: 0, left: 0, done: false}
105+
106+
// insertPadLengthAll = true means PKCS#7 (padding length inserted in each padding slot),
107+
// otherwise false means padding length inserted only in the last slot (the rest is random bytes)
108+
func PaddedReader(r io.Reader, blockSize byte, insertPadLengthAll bool) io.Reader {
109+
return &paddedReader{Reader: r, size: blockSize, count: 0, left: 0, done: false, insertPadLengthAll: insertPadLengthAll}
91110
}

crypto/pad_test.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import (
3333

3434
func TestOneBlock(t *testing.T) {
3535
buf := bytes.NewBufferString("4321")
36-
reader := PaddedReader(buf, 6)
36+
reader := PaddedReader(buf, 6, true)
3737
var out [12]byte
3838
n, err := reader.Read(out[:])
3939
if err != nil && err != io.EOF {
@@ -50,7 +50,7 @@ func TestOneBlock(t *testing.T) {
5050

5151
func TestFullPadding(t *testing.T) {
5252
buf := bytes.NewBufferString("1234")
53-
reader := PaddedReader(buf, 4)
53+
reader := PaddedReader(buf, 4, true)
5454

5555
var out [8]byte
5656
n, err := io.ReadFull(reader, out[:])
@@ -68,7 +68,7 @@ func TestFullPadding(t *testing.T) {
6868

6969
func TestManyBlocks(t *testing.T) {
7070
buf := bytes.NewBufferString("1234")
71-
reader := PaddedReader(buf, 3)
71+
reader := PaddedReader(buf, 3, true)
7272
var out [3]byte
7373
n, err := io.ReadFull(reader, out[:])
7474
if err != nil {
@@ -91,7 +91,7 @@ func TestManyBlocks(t *testing.T) {
9191

9292
func TestPaddingInMultipleCalls(t *testing.T) {
9393
buf := bytes.NewBufferString("1")
94-
reader := PaddedReader(buf, 6)
94+
reader := PaddedReader(buf, 6, false)
9595
var out [3]byte
9696
n, err := io.ReadFull(reader, out[:])
9797

@@ -122,7 +122,7 @@ func (r failingReader) Read(buf []byte) (int, error) {
122122
}
123123

124124
func TestFailingReader(t *testing.T) {
125-
reader := PaddedReader(failingReader{}, 8)
125+
reader := PaddedReader(failingReader{}, 8, false)
126126
var out [8]byte
127127
_, err := io.ReadFull(reader, out[:])
128128

0 commit comments

Comments
 (0)