-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #42 from microsoft/des
Add support for DES
- Loading branch information
Showing
5 changed files
with
1,869 additions
and
62 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
//go:build windows | ||
// +build windows | ||
|
||
package cng | ||
|
||
import ( | ||
"errors" | ||
|
||
"github.com/microsoft/go-crypto-winnative/internal/bcrypt" | ||
) | ||
|
||
type cipherAlgorithm struct { | ||
handle bcrypt.ALG_HANDLE | ||
allowedKeyLengths bcrypt.KEY_LENGTHS_STRUCT | ||
} | ||
|
||
func loadCipher(id, mode string) (cipherAlgorithm, error) { | ||
v, err := loadOrStoreAlg(id, bcrypt.ALG_NONE_FLAG, mode, func(h bcrypt.ALG_HANDLE) (interface{}, error) { | ||
if mode != "" { | ||
// Windows 8 added support to set the CipherMode value on a key, | ||
// but Windows 7 requires that it be set on the algorithm before key creation. | ||
err := setString(bcrypt.HANDLE(h), bcrypt.CHAINING_MODE, mode) | ||
if err != nil { | ||
return nil, err | ||
} | ||
} | ||
lengths, err := getKeyLengths(bcrypt.HANDLE(h)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return cipherAlgorithm{h, lengths}, nil | ||
}) | ||
if err != nil { | ||
return cipherAlgorithm{}, nil | ||
} | ||
return v.(cipherAlgorithm), nil | ||
} | ||
|
||
func newCipherHandle(id, mode string, key []byte) (bcrypt.KEY_HANDLE, error) { | ||
h, err := loadCipher(id, mode) | ||
if err != nil { | ||
return 0, err | ||
} | ||
if !keyIsAllowed(h.allowedKeyLengths, uint32(len(key)*8)) { | ||
return 0, errors.New("crypto/cipher: invalid key size") | ||
} | ||
var kh bcrypt.KEY_HANDLE | ||
err = bcrypt.GenerateSymmetricKey(h.handle, &kh, nil, key, 0) | ||
if err != nil { | ||
return 0, err | ||
} | ||
return kh, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
//go:build windows | ||
// +build windows | ||
|
||
package cng | ||
|
||
import ( | ||
"crypto/cipher" | ||
"runtime" | ||
|
||
"github.com/microsoft/go-crypto-winnative/internal/bcrypt" | ||
"github.com/microsoft/go-crypto-winnative/internal/subtle" | ||
) | ||
|
||
const desBlockSize = 8 | ||
|
||
type desCipher struct { | ||
kh bcrypt.KEY_HANDLE | ||
key []byte | ||
} | ||
|
||
func NewDESCipher(key []byte) (cipher.Block, error) { | ||
kh, err := newCipherHandle(bcrypt.DES_ALGORITHM, "", key) | ||
if err != nil { | ||
return nil, err | ||
} | ||
c := &desCipher{kh: kh, key: make([]byte, len(key))} | ||
copy(c.key, key) | ||
runtime.SetFinalizer(c, (*desCipher).finalize) | ||
return c, nil | ||
} | ||
|
||
func NewTripleDESCipher(key []byte) (cipher.Block, error) { | ||
kh, err := newCipherHandle(bcrypt.DES3_ALGORITHM, "", key) | ||
if err != nil { | ||
return nil, err | ||
} | ||
c := &desCipher{kh: kh, key: make([]byte, len(key))} | ||
copy(c.key, key) | ||
runtime.SetFinalizer(c, (*desCipher).finalize) | ||
return c, nil | ||
} | ||
|
||
func (c *desCipher) finalize() { | ||
bcrypt.DestroyKey(c.kh) | ||
} | ||
|
||
func (c *desCipher) BlockSize() int { return desBlockSize } | ||
|
||
func (c *desCipher) Encrypt(dst, src []byte) { | ||
if len(src) < desBlockSize { | ||
panic("crypto/des: input not full block") | ||
} | ||
if len(dst) < desBlockSize { | ||
panic("crypto/des: output not full block") | ||
} | ||
// cypher.Block.Encrypt() is documented to encrypt one full block | ||
// at a time, so we truncate the input and output to the block size. | ||
dst, src = dst[:desBlockSize], src[:desBlockSize] | ||
if subtle.InexactOverlap(dst, src) { | ||
panic("crypto/des: invalid buffer overlap") | ||
} | ||
var ret uint32 | ||
err := bcrypt.Encrypt(c.kh, src, nil, nil, dst, &ret, 0) | ||
if err != nil { | ||
panic(err) | ||
} | ||
if int(ret) != len(src) { | ||
panic("crypto/des: plaintext not fully encrypted") | ||
} | ||
runtime.KeepAlive(c) | ||
} | ||
|
||
func (c *desCipher) Decrypt(dst, src []byte) { | ||
if len(src) < desBlockSize { | ||
panic("crypto/des: input not full block") | ||
} | ||
if len(dst) < desBlockSize { | ||
panic("crypto/des: output not full block") | ||
} | ||
// cypher.Block.Decrypt() is documented to decrypt one full block | ||
// at a time, so we truncate the input and output to the block size. | ||
dst, src = dst[:desBlockSize], src[:desBlockSize] | ||
if subtle.InexactOverlap(dst, src) { | ||
panic("crypto/des: invalid buffer overlap") | ||
} | ||
var ret uint32 | ||
err := bcrypt.Decrypt(c.kh, src, nil, nil, dst, &ret, 0) | ||
if err != nil { | ||
panic(err) | ||
} | ||
if int(ret) != len(src) { | ||
panic("crypto/des: plaintext not fully decrypted") | ||
} | ||
runtime.KeepAlive(c) | ||
} | ||
|
||
func (c *desCipher) NewCBCEncrypter(iv []byte) cipher.BlockMode { | ||
return newCBC(true, bcrypt.DES_ALGORITHM, c.key, iv) | ||
} | ||
|
||
func (c *desCipher) NewCBCDecrypter(iv []byte) cipher.BlockMode { | ||
return newCBC(false, bcrypt.DES_ALGORITHM, c.key, iv) | ||
} |
Oops, something went wrong.