// Like GosaDecrypt() but operates in-place on buf. // Returns true if decryption successful and false if not. // If false is returned, the buffer contents may be destroyed, but only // if further decryption attempts with other keys would be pointless anyway, // because of some fatal condition (such as the data not being a multiple of // the cipher's block size). func GosaDecryptBuffer(buf *bytes.Buffer, key string) bool { buf.TrimSpace() if buf.Len() < 11 { return false } // minimum length of unencrypted <xml></xml> data := buf.Bytes() if string(data[0:5]) == "<xml>" { return true } // Fixes the following: // * gosa-si bug in the following line: // if( $client_answer =~ s/session_id=(\d+)$// ) { // This leaves the "." before "session_id" which breaks base64 // * new gosa-si protocol has ";IP:PORT" appended to message // which also breaks base64 for semicolon_period := 0; semicolon_period < len(data); semicolon_period++ { if data[semicolon_period] == ';' || data[semicolon_period] == '.' { buf.Trim(0, semicolon_period) data = buf.Bytes() break } } aescipher, _ := aes.NewCipher([]byte(util.Md5sum(key))) crypter := cipher.NewCBCDecrypter(aescipher, config.InitializationVector) cryptotest := make([]byte, (((3*aes.BlockSize)+2)/3)<<2) n := copy(cryptotest, data) cryptotest = cryptotest[0:n] cryptotest = util.Base64DecodeInPlace(cryptotest) n = (len(cryptotest) / aes.BlockSize) * aes.BlockSize cryptotest = cryptotest[0:n] crypter.CryptBlocks(cryptotest, cryptotest) if !strings.Contains(string(cryptotest), "<xml>") { return false } data = util.Base64DecodeInPlace(data) buf.Trim(0, len(data)) data = buf.Bytes() if buf.Len()%aes.BlockSize != 0 { // this condition is fatal => further decryption attempts are pointless buf.Reset() return false } crypter = cipher.NewCBCDecrypter(aescipher, config.InitializationVector) crypter.CryptBlocks(data, data) buf.TrimSpace() // removes 0 padding, too return true }
func DecryptFile(filepath string, key []byte) { fmt.Println() cipherText, err := os.Open(filepath) if err != nil { fmt.Println("ERROR:", err) } defer cipherText.Close() plainText, err := os.Create(filepath + ".dec") if err != nil { fmt.Println("ERROR:", err) } defer plainText.Close() iv := make([]byte, 16) //AES const _, err = cipherText.Read(iv) fmt.Println("iv=", iv[:]) if err != nil { fmt.Println("ERROR:", err) } encBlock := make([]byte, 16) // AES const block, err := aes.NewCipher(key) if err != nil { fmt.Println("ERROR:", err) } mode := cipher.NewCBCDecrypter(block, iv) // we have decrypter, can loop over file contents now // know size so can not get EOF'd stats, err := cipherText.Stat() if err != nil { fmt.Println("ERROR:", err) } var ReadAmt int64 = 16 message := make([]byte, 16) for ReadAmt != stats.Size() { //read in file, decrypt, check for end, if so strip padding if _, err := cipherText.Read(encBlock); err != nil { fmt.Println("ERROR:", err) } ReadAmt += 16 // AES const mode.CryptBlocks(message, encBlock) //check for end, if so strip pad fmt.Println("encrypt=", encBlock[:]) fmt.Println("message=", message[:]) if ReadAmt == stats.Size() { pad := message[15] message = message[:16-pad] } plainText.Write(message) } }
func cipherAES(key, iv []byte, isRead bool) interface{} { block, _ := aes.NewCipher(key) if isRead { return cipher.NewCBCDecrypter(block, iv) } return cipher.NewCBCEncrypter(block, iv) }
// Open decrypts and authenticates the ciphertext. func (ctx *cbcAEAD) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { if len(ciphertext) < ctx.authtagBytes { return nil, errors.New("square/go-jose: invalid ciphertext (too short)") } offset := len(ciphertext) - ctx.authtagBytes expectedTag := ctx.computeAuthTag(data, nonce, ciphertext[:offset]) match := subtle.ConstantTimeCompare(expectedTag, ciphertext[offset:]) if match != 1 { return nil, errors.New("square/go-jose: invalid ciphertext (auth tag mismatch)") } cbc := cipher.NewCBCDecrypter(ctx.blockCipher, nonce) // Make copy of ciphertext buffer, don't want to modify in place buffer := append([]byte{}, []byte(ciphertext[:offset])...) if len(buffer)%ctx.blockCipher.BlockSize() > 0 { return nil, errors.New("square/go-jose: invalid ciphertext (invalid length)") } cbc.CryptBlocks(buffer, buffer) // Remove padding plaintext, err := unpadBuffer(buffer, ctx.blockCipher.BlockSize()) if err != nil { return nil, err } ret, out := resize(dst, len(dst)+len(plaintext)) copy(out, plaintext) return ret, nil }
func (s SecureStorage) decrypt(text1 []byte) (string, error) { var data []byte // The decrypt may be called with un-encrypted data (the hash key to random, // may be OK in some cases thus thiis has to be verified by the caller) defer func() (string, error) { if r := recover(); r != nil { return "", fmt.Errorf("during decryption: '%v'", text1) } return string(data), nil }() text, err := base64.StdEncoding.DecodeString(string(text1)) if err != nil { return "", fmt.Errorf("during decryption: '%v', error: %v", text, err) } block, err := aes.NewCipher(s.secret) if err != nil { return "", fmt.Errorf("during decryption: '%v', error: %v", text, err) } if len(text) < aes.BlockSize { return "", fmt.Errorf("Error during decryption: Ciphertext too short") } iv := text[:aes.BlockSize] dtext := text[aes.BlockSize:] mode := cipher.NewCBCDecrypter(block, iv) mode.CryptBlocks(dtext, dtext) return string(dtext), nil }
func (c *AESCBCBlockCipher) decrypt(cipherText []byte) ([]byte, error) { if c.err != nil { return nil, c.err } bs := c.block.BlockSize() if len(cipherText)%bs != 0 { return nil, fmt.Errorf("Need a multiple of the blocksize") } mode := cipher.NewCBCDecrypter(c.block, c.iv) // CryptBlocks can work in-place if the two arguments are the same. mode.CryptBlocks(cipherText, cipherText) // If the original plainText lengths are not a multiple of the block // size, padding would have to be added when encrypting, which would be // removed at this point. For an example, see // https://tools.ietf.org/html/rfc5246#section-6.2.3.2. However, it's // critical to note that cipherTexts must be authenticated (i.e. by // using crypto/hmac) before being decrypted in order to avoid creating // a padding oracle. return stripPadding(cipherText), nil }
func (s *descbc) Decrypt(salt []byte, algo, usage int, data []byte) ([]byte, error) { var h hash.Hash switch algo { case cryptDesCbcMd5: h = md5.New() case cryptDesCbcMd4: h = md4.New() default: return nil, ErrProtocol } if (len(data) & 7) != 0 { return nil, ErrProtocol } iv := [8]byte{} b, _ := des.NewCipher(s.key) c := cipher.NewCBCDecrypter(b, iv[:]) c.CryptBlocks(data, data) chk := make([]byte, h.Size()) h.Write(data[:8]) h.Write(chk) // Just need h.Size() zero bytes instead of the checksum h.Write(data[8+len(chk):]) h.Sum(chk[:0]) if subtle.ConstantTimeCompare(chk, data[8:8+len(chk)]) != 1 { return nil, ErrProtocol } return data[8+len(chk):], nil }
// Takes json string func Decrypt(s string, password string) (string, error) { var obj Crypto if err := json.Unmarshal([]byte(s), &obj); err != nil { return "", err } iv, err := base64.StdEncoding.DecodeString(obj.Iv) if err != nil { return "", err } salt, err := base64.StdEncoding.DecodeString(obj.Salt) if err != nil { return "", err } ct, err := base64.StdEncoding.DecodeString(obj.Ct) if err != nil { return "", err } key := buildDecryptionKey(password, string(salt)) block, err := aes.NewCipher(key[:32]) if err != nil { panic(err) } decrypter := cipher.NewCBCDecrypter(block, iv) data := make([]byte, len(ct)) decrypter.CryptBlocks(data, ct) return string(data), nil }
// AES256CBCDecrypt decrypts the given ciphertext with AES-256 in CBC mode and // returns the resulting plaintext. The supplied key must be 32 bytes long and // the ciphertext must be prepended by the corresponding IV. func AES256CBCDecrypt(key, ciphertext []byte) (plaintext []byte) { if len(key) != 32 { panic(log.Critical("cipher: AES-256 key is not 32 bytes long")) } block, _ := aes.NewCipher(key) // correct key length was enforced above // The IV needs to be unique, but not secure. Therefore it's common to // include it at the beginning of the ciphertext. if len(ciphertext) < aes.BlockSize { panic(log.Critical("cipher: ciphertext too short")) } iv := ciphertext[:aes.BlockSize] ciphertext = ciphertext[aes.BlockSize:] plaintext = make([]byte, len(ciphertext)) // CBC mode always works in whole blocks. if len(ciphertext)%aes.BlockSize != 0 { panic(log.Critical("cipher: ciphertext is not a multiple of the block size")) } mode := cipher.NewCBCDecrypter(block, iv) // CryptBlocks can work in-place if the two arguments are the same. mode.CryptBlocks(plaintext, ciphertext) return }
// Decrypt decrypts the provided ciphertext, reversing the Encrypt method. func Decrypt(ciphertext []byte, passphrase string) []byte { key := makeKeySlice(passphrase) block, err := aes.NewCipher(key) if err != nil { panic(err) } iv := ciphertext[:aes.BlockSize] ciphertext = ciphertext[aes.BlockSize:] if len(ciphertext)%aes.BlockSize != 0 { panic("ciphertext is not a multiple of the block size") } mode := cipher.NewCBCDecrypter(block, iv) // CryptBlocks can work in-place if the two arguments are the same. mode.CryptBlocks(ciphertext, ciphertext) padLength := int(uint8(ciphertext[len(ciphertext)-1])) unpadded := ciphertext[:len(ciphertext)-padLength] return unpadded }
func NewAesCBCCrypter(key []byte, iv []byte) (*AesCBCCrypter, error) { l := len(key) if l != 32 && l != 24 && l != 16 { return nil, errors.New("The key argument should be the AES key, either 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256.") } block, _ := aes.NewCipher(key) blockSize := block.BlockSize() if len(iv) != blockSize { return nil, errors.New("The length of iv must be the same as the Block's block size " + strconv.Itoa(blockSize)) } this := &AesCBCCrypter{ blockSize: blockSize, encryptBlockMode: cipher.NewCBCEncrypter(block, iv), decryptBlockMode: cipher.NewCBCDecrypter(block, iv), padding: &PKCS5Padding{ BlockSize: blockSize, }, } return this, nil }
func (c LocalCrypter) Decrypt(b64ciphertext Ciphertext, decryptParams DecryptParams) (string, error) { key, err := localKey() if err != nil { return "", fmt.Errorf("Error retrieving local key: %s", err) } block, err := aes.NewCipher(key) if err != nil { return "", fmt.Errorf("Error creating AES cipher: %s", err) } ciphertext, err := base64.StdEncoding.DecodeString(string(b64ciphertext)) if err != nil { return "", fmt.Errorf("Ciphertext is not valid base64 encoded in secret '%s'", b64ciphertext) } if len(ciphertext) < aes.BlockSize { return "", fmt.Errorf("Ciphertext too short in secret '%s'", ciphertext) } iv := []byte(ciphertext[:aes.BlockSize]) ciphertext = ciphertext[aes.BlockSize:] if len(ciphertext)%aes.BlockSize != 0 { return "", fmt.Errorf("Ciphertext is not a multiple of the block size in secret '%s'", ciphertext) } mode := cipher.NewCBCDecrypter(block, iv) plaintext := make([]byte, len(ciphertext)) mode.CryptBlocks(plaintext, []byte(ciphertext)) length := len(plaintext) unpadding := int(plaintext[length-1]) plaintext = plaintext[:(length - unpadding)] return string(plaintext), nil }
// Get the plain text out of a frame func (fr *Frame) PlainText() []DIFs { if fr.Key != "" { // Check whether the encrypted value is too long, if this is the case it is // a plaintext extension and we have to parse this data if (len(fr.Value[fr.ValueStart()*2:]) / 2) > fr.ConfigurationLength() { return getDIFs(fr.Value[fr.ValueStart()*2+fr.ConfigurationLength()*2:]) } //if(fr.ValueStart()+fr.ConfigurationLength())*2 key, err := hex.DecodeString(fr.Key) if err == nil { ciphertext, err := hex.DecodeString(fr.Value[fr.ValueStart()*2:]) if err == nil { block, err := aes.NewCipher(key) if err == nil { iv, err := hex.DecodeString(fr.IV()) if err == nil { mode := cipher.NewCBCDecrypter(block, iv) mode.CryptBlocks(ciphertext, ciphertext) plaintext := fmt.Sprintf("%s\n", hex.EncodeToString(ciphertext)) values := getDIFs(plaintext) return values } } } } } return nil }
func cipher3DES(key, iv []byte, isRead bool) interface{} { // 创建3DES算法对称加密 block, _ := des.NewTripleDESCipher(key) if isRead { return cipher.NewCBCDecrypter(block, iv) } return cipher.NewCBCEncrypter(block, iv) }
// Decode decodes the given token and return its data // and creation time in UTC. func (tok *T) Decode(token []byte) (data []byte, creation time.Time, err error) { raw := make([]byte, base64.RawURLEncoding.DecodedLen(len(token))) n, err := base64.RawURLEncoding.Decode(raw, token) if err != nil { return nil, time.Time{}, err } raw = raw[:n] hash := tok.hmac() if len(raw) < aes.BlockSize*2+hash.Size() { return nil, time.Time{}, ErrInvalidToken } soff := len(raw) - hash.Size() // signature offset hash.Write(raw[:soff]) want := hash.Sum(nil) have := raw[soff:] if !hmac.Equal(want, have) { return nil, time.Time{}, ErrInvalidTokenSignature } iv := raw[:aes.BlockSize] body := raw[aes.BlockSize:soff] if len(body)%aes.BlockSize != 0 { return nil, time.Time{}, ErrInvalidToken } mode := cipher.NewCBCDecrypter(tok.aes, iv) mode.CryptBlocks(body, body) ts := time.Unix(int64(binary.BigEndian.Uint32(body)), 0) body, err = pkcs7Unpad(body, aes.BlockSize) if err != nil { return nil, time.Time{}, err } return body[4:], ts.UTC(), nil }
// Decrypt 方法用于对密文进行解密 // // 返回解密后的消息,CropId/AppId, 或者错误信息 func (w messageCrypter) decrypt(text string) ([]byte, string, error) { var msgDecrypt []byte var id string deciphered, err := base64.StdEncoding.DecodeString(text) if err != nil { return nil, "", err } c, err := aes.NewCipher(w.key) if err != nil { return nil, "", err } cbc := cipher.NewCBCDecrypter(c, w.iv) cbc.CryptBlocks(deciphered, deciphered) decoded := delDecode(deciphered) buf := bytes.NewBuffer(decoded[16:20]) var msgLen int32 binary.Read(buf, binary.BigEndian, &msgLen) msgDecrypt = decoded[20 : 20+msgLen] id = string(decoded[20+msgLen:]) return msgDecrypt, id, nil }
func decryptData(secret_key []byte, encrypted_data []byte) (string, error) { block, err := aes.NewCipher(secret_key) if err != nil { return "", err } if len(encrypted_data) < aes.BlockSize { return "", errors.New("encrypted data is less than BlockSize") } iv := encrypted_data[:aes.BlockSize] data := encrypted_data[aes.BlockSize:] if len(data)%aes.BlockSize != 0 { return "", errors.New("encrypted data is not a multiple of block size") } mode := cipher.NewCBCDecrypter(block, iv) mode.CryptBlocks(data, data) // remove padding trimmed_data := strings.TrimRight(string(data), "=") return trimmed_data, nil }
func version1Decoder(key []byte, iv, encryptedData string) (interface{}, error) { ciphertext := decodeBase64(encryptedData) initVector := decodeBase64(iv) keySha := sha256.Sum256(key) block, err := aes.NewCipher(keySha[:]) if err != nil { return nil, err } if len(ciphertext)%aes.BlockSize != 0 { return nil, errors.New("Ciphertext is wrong length") } mode := cipher.NewCBCDecrypter(block, initVector) mode.CryptBlocks(ciphertext, ciphertext) ciphertext = unPKCS7Padding(ciphertext) var item version1Item _ = json.Unmarshal(ciphertext, &item) if item.Content == nil { return nil, fmt.Errorf("Decryption failed, check your decryption key.") } return item.Content, nil }
// Returns a new Reader that reads from r // // The header section storing the salt and keys is read from r to verify the file is // actually a psafe3 file and the password is correct. // // All reads from this reader will return unencrypted data. func NewReader(r io.Reader, password string) (*Reader, error) { reader := &Reader{r: r, password: password} var header psv3Header binary.Read(r, binary.LittleEndian, &header) if string(header.Tag[:]) != "PWS3" { return nil, ErrBadFileType } sk := computeStretchKey(header.Salt[:], []byte(password), int(header.Iter)) hashsk := sha256.Sum256(sk) if hashsk != header.HashPPrime { return nil, ErrInvalidPassword } var key, hmacKey [32]byte tfish, _ := twofish.NewCipher(sk) tfish.Decrypt(key[:16], header.B1[:]) tfish.Decrypt(key[16:], header.B2[:]) tfish.Decrypt(hmacKey[:16], header.B3[:]) tfish.Decrypt(hmacKey[16:], header.B4[:]) tfish, _ = twofish.NewCipher(key[:]) reader.tfishDecrypter = cipher.NewCBCDecrypter(tfish, header.IV[:]) reader.hmacHash = hmac.New(sha256.New, hmacKey[:]) return reader, nil }
func TestCBC_AES(t *testing.T) { for _, tt := range cbcAESTests { test := tt.name c, err := aes.NewCipher(tt.key) if err != nil { t.Errorf("%s: NewCipher(%d bytes) = %s", test, len(tt.key), err) continue } encrypter := cipher.NewCBCEncrypter(c, tt.iv) d := make([]byte, len(tt.in)) encrypter.CryptBlocks(d, tt.in) if !bytes.Equal(tt.out, d) { t.Errorf("%s: CBCEncrypter\nhave %x\nwant %x", test, d, tt.out) } decrypter := cipher.NewCBCDecrypter(c, tt.iv) p := make([]byte, len(d)) decrypter.CryptBlocks(p, d) if !bytes.Equal(tt.in, p) { t.Errorf("%s: CBCDecrypter\nhave %x\nwant %x", test, d, tt.in) } } }
func decryptMessage(msg []byte, skey []byte) { verbose("Decrypting message...", 2) /* The first 8 bytes are "Salted__", followed by 8 bytes of salt. */ salt := msg[8:16] msg = msg[16:] /* Hack! Older versions of jass(1) generated a session key with a * trailing '\n', which we have to strip here. Properly generated * session keys (as this version provides) should _not_ have a '\n' as * the last char. An old session key would be 45 bytes (32 random * bytes, base64-encoded => 44 bytes + one trailing '\n'), so trim that. * * Backwards compatibility is a bitch. */ if len(skey) == 45 { skey = skey[:len(skey)-1] } key, iv := bytesToKey(skey, salt) block, err := aes.NewCipher(key) if err != nil { fail(fmt.Sprintf("Unable to set up new cipher: %s\n", err)) } if len(msg)%aes.BlockSize != 0 { fail("ciphertext is not a multiple of the block size") } mode := cipher.NewCBCDecrypter(block, iv) mode.CryptBlocks(msg, msg) msg = unpadBuffer(msg) fmt.Printf("%v", string(msg)) }
// 使用aes算法,解密指定内容 func DecryptAes(cryptData, key []byte) ([]byte, error) { if (len(cryptData) == 0) || (len(key) == 0) { return nil, errors.New("decrypt data or secret key is empty") } block, err := aes.NewCipher(key) if err != nil { return nil, err } blockMode := cipher.NewCBCDecrypter(block, key[:aes.BlockSize]) rawData := make([]byte, len(cryptData)) // CryptBlocks(dst, src []byte), Dst and src may point to the same memory. blockMode.CryptBlocks(rawData, cryptData) unpadding := int(rawData[len(rawData)-1]) if len(rawData) > unpadding { rawData = rawData[:(len(rawData) - unpadding)] } else { return nil, errors.New("decrypt raw data error, key is correct?") } return rawData, nil }
func decodeCookie(encodedCookie string, key, iv []byte) (map[string]interface{}, error) { sessionBytes, err := base64.URLEncoding.DecodeString(encodedCookie) if err != nil { log.Error("<decodeCookie> ", "base64.Decodestring:", err) return nil, err } aesCipher, err := aes.NewCipher(key) if err != nil { log.Error("<decodeCookie> ", "aes.NewCipher:", err) return nil, err } decrypter := cipher.NewCBCDecrypter(aesCipher, iv) decrypter.CryptBlocks(sessionBytes, sessionBytes) buf := bytes.NewBuffer(sessionBytes) var gobLen int32 binary.Read(buf, binary.BigEndian, &gobLen) gobBytes := sessionBytes[4 : 4+gobLen] session, err := decodeGob(gobBytes) if err != nil { log.Error("<decodeCookie> ", "decodeGob:", err) return nil, err } return session, nil }
/* 对称解密, 不会修改输入的数据 */ func DecryptV2(key []byte, data []byte) (output []byte, err error) { if len(data) < 16+64 { return nil, errors.New("[kmgCipher.Decrypt] input data too small") } keyHash := sha512.Sum512(key) aseKey := keyHash[:32] cbcIv := data[:16] block, err := aes.NewCipher(aseKey) if err != nil { return nil, err } if len(data)%block.BlockSize() != 0 { return nil, errors.New("[kmgCipher.Decrypt] input not full blocks") } output = make([]byte, len(data)-16) blockmode := cipher.NewCBCDecrypter(block, cbcIv) blockmode.CryptBlocks(output, data[16:]) paddingSize := int(output[len(output)-1]) if paddingSize > block.BlockSize() { return nil, errors.New("[kmgCipher.Decrypt] paddingSize out of range") } beforeCbcSize := len(data) - paddingSize - 64 - 16 hashData := sha512.Sum512(output[:beforeCbcSize]) if !bytes.Equal(hashData[:], output[beforeCbcSize:beforeCbcSize+64]) { return nil, errors.New("[kmgCipher.Decrypt] hash not match") } return output[:beforeCbcSize], nil }
/* rezult 0 - err 1 - ok 2 - капча введена не правильно 3 - капча устарела 4 - попытка повторного использования капчи */ func (t *t_captchaserv) check(w http.ResponseWriter, r *http.Request) { defer func() { if e := recover(); e != nil { fmt.Println(fmt.Errorf("%v", e)) fmt.Fprint(w, "0") } }() var ( state_id uint8 = 0 ) decryptstr := make([]byte, 16) // /captcha/check/+1byte node id param := strings.SplitN(r.URL.Path[len(v_captcha.c.Urlcheck)+1:], "/", 2) encryptstr, _ := base64.URLEncoding.DecodeString(param[0]) if t.iv[1].id == encryptstr[0] { state_id = 1 } else if t.iv[0].id != encryptstr[0] { fmt.Fprint(w, "3") return } t.rwmu_chang_state.RLock() decrypter0 := cipher.NewCBCDecrypter(t.bcipher, t.iv[state_id].val) t.rwmu_chang_state.RUnlock() decrypter0.CryptBlocks(decryptstr, encryptstr[1:]) if decryptstr[0] != 33 { fmt.Fprint(w, "3") return } id, err := strconv.ParseUint(strings.TrimSpace(string(decryptstr[5:])), 10, 32) if err != nil { fmt.Fprint(w, "0") return } if string(decryptstr[1:5]) == param[1] { if t.db[id] == 100 { fmt.Fprint(w, "4") return } fmt.Fprint(w, "1") t.db[id] = 100 return } if t.db[id] > 1 { fmt.Fprint(w, "4") t.db[id] = 100 return } fmt.Fprint(w, "2") t.db[id]++ }
func BenchmarkDescryptAesCbc(b *testing.B) { key := randomBytes(16) iv := randomBytes(16) encrypted, err := EncryptIV(original, key, iv) if err != nil { b.Fatal(err) } counter := 0 dataLen := len(encrypted) aesCipher, err := aes.NewCipher(key) if err != nil { b.Fatal(err) } dec := cipher.NewCBCDecrypter(aesCipher, iv) t := time.Now() decrypted := make([]byte, len(encrypted)) b.SetBytes(int64(len(encrypted))) b.ResetTimer() for i := 0; i < b.N; i++ { dec.CryptBlocks(decrypted, encrypted) counter += dataLen } b.StopTimer() ts := time.Since(t) b.Logf("decryption speed: %.2f Mbit/s", float64(counter)*8/ts.Seconds()/1024/1024) }
func pbDecrypterFor(algorithm pkix.AlgorithmIdentifier, password []byte) (cipher.BlockMode, int, error) { var cipherType pbeCipher switch { case algorithm.Algorithm.Equal(oidPBEWithSHAAnd3KeyTripleDESCBC): cipherType = shaWithTripleDESCBC{} case algorithm.Algorithm.Equal(oidPBEWithSHAAnd40BitRC2CBC): cipherType = shaWith40BitRC2CBC{} default: return nil, 0, NotImplementedError("algorithm " + algorithm.Algorithm.String() + " is not supported") } var params pbeParams if err := unmarshal(algorithm.Parameters.FullBytes, ¶ms); err != nil { return nil, 0, err } key := cipherType.deriveKey(params.Salt, password, params.Iterations) iv := cipherType.deriveIV(params.Salt, password, params.Iterations) block, err := cipherType.create(key) if err != nil { return nil, 0, err } return cipher.NewCBCDecrypter(block, iv), block.BlockSize(), nil }
// DecryptPEMBlock takes a password encrypted PEM block and the password used to // encrypt it and returns a slice of decrypted DER encoded bytes. It inspects // the DEK-Info header to determine the algorithm used for decryption. If no // DEK-Info header is present, an error is returned. If an incorrect password // is detected an IncorrectPasswordError is returned. Because of deficiencies // in the encrypted-PEM format, it's not always possible to detect an incorrect // password. In these cases no error will be returned but the decrypted DER // bytes will be random noise. func DecryptPEMBlock(b *pem.Block, password []byte) ([]byte, error) { dek, ok := b.Headers["DEK-Info"] if !ok { return nil, errors.New("x509: no DEK-Info header in block") } idx := strings.Index(dek, ",") if idx == -1 { return nil, errors.New("x509: malformed DEK-Info header") } mode, hexIV := dek[:idx], dek[idx+1:] ciph := cipherByName(mode) if ciph == nil { return nil, errors.New("x509: unknown encryption mode") } iv, err := hex.DecodeString(hexIV) if err != nil { return nil, err } if len(iv) != ciph.blockSize { return nil, errors.New("x509: incorrect IV size") } // Based on the OpenSSL implementation. The salt is the first 8 bytes // of the initialization vector. key := ciph.deriveKey(password, iv[:8]) block, err := ciph.cipherFunc(key) if err != nil { return nil, err } data := make([]byte, len(b.Bytes)) dec := cipher.NewCBCDecrypter(block, iv) dec.CryptBlocks(data, b.Bytes) // Blocks are padded using a scheme where the last n bytes of padding are all // equal to n. It can pad from 1 to blocksize bytes inclusive. See RFC 1423. // For example: // [x y z 2 2] // [x y 7 7 7 7 7 7 7] // If we detect a bad padding, we assume it is an invalid password. dlen := len(data) if dlen == 0 || dlen%ciph.blockSize != 0 { return nil, errors.New("x509: invalid padding") } last := int(data[dlen-1]) if dlen < last { return nil, IncorrectPasswordError } if last == 0 || last > ciph.blockSize { return nil, IncorrectPasswordError } for _, val := range data[dlen-last:] { if int(val) != last { return nil, IncorrectPasswordError } } return data[:dlen-last], nil }
func decryptDES(src, key, privParam []byte) (dst []byte, err error) { if len(src)%des.BlockSize != 0 { err = ArgumentError{ Value: len(src), Message: "Invalid DES cipher length", } return } if len(privParam) != 8 { err = ArgumentError{ Value: len(privParam), Message: "Invalid DES PrivParameter length", } return } block, err := des.NewCipher(key[:8]) if err != nil { return } iv := xor(key[8:16], privParam) dst = make([]byte, len(src)) mode := cipher.NewCBCDecrypter(block, iv) mode.CryptBlocks(dst, src) return }
// ciphertext = AES_Encrypt[random(16B) + msg_len(4B) + rawXMLMsg + appId] func AESDecryptMsg(ciphertext []byte, appId string, aesKey [32]byte) (random, rawXMLMsg []byte, err error) { const ( BLOCK_SIZE = 32 // PKCS#7 BLOCK_MASK = BLOCK_SIZE - 1 // BLOCK_SIZE 为 2^n 时, 可以用 mask 获取针对 BLOCK_SIZE 的余数 ) if len(ciphertext) < BLOCK_SIZE { err = fmt.Errorf("the length of ciphertext too short: %d", len(ciphertext)) return } if len(ciphertext)&BLOCK_MASK != 0 { err = fmt.Errorf("ciphertext is not a multiple of the block size, the length is %d", len(ciphertext)) return } plaintext := make([]byte, len(ciphertext)) // len(plaintext) >= BLOCK_SIZE // 解密 block, err := aes.NewCipher(aesKey[:]) if err != nil { panic(err) } mode := cipher.NewCBCDecrypter(block, aesKey[:16]) mode.CryptBlocks(plaintext, ciphertext) // PKCS#7 去除补位 amountToPad := int(plaintext[len(plaintext)-1]) if amountToPad < 1 || amountToPad > BLOCK_SIZE { err = fmt.Errorf("the amount to pad is invalid: %d", amountToPad) return } plaintext = plaintext[:len(plaintext)-amountToPad] // 反拼接 // len(plaintext) == 16+4+len(rawXMLMsg)+len(appId) if len(plaintext) <= 20 { err = fmt.Errorf("plaintext too short, the length is %d", len(plaintext)) return } rawXMLMsgLen := int(decodeNetworkByteOrder(plaintext[16:20])) if rawXMLMsgLen < 0 { err = fmt.Errorf("invalid msg length: %d", rawXMLMsgLen) return } appIdOffset := 20 + rawXMLMsgLen if len(plaintext) <= appIdOffset { err = fmt.Errorf("msg length too large: %d", rawXMLMsgLen) return } appIdHave := string(plaintext[appIdOffset:]) if appIdHave != appId { err = fmt.Errorf("appId mismatch, have: %s, want: %s", appIdHave, appId) return } random = plaintext[:16:20] rawXMLMsg = plaintext[20:appIdOffset] return }