Skip to content

Commit

Permalink
Squash commits and release on GitHub
Browse files Browse the repository at this point in the history
  • Loading branch information
bobziuchkovski committed Feb 4, 2016
0 parents commit ba8d395
Show file tree
Hide file tree
Showing 15 changed files with 1,228 additions and 0 deletions.
18 changes: 18 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
language: go
sudo: false

go:
- 1.2.2
- 1.3.3
- 1.4.3
- 1.5.3
- tip

matrix:
allow_failures:
- go: tip

script:
- go tool -n vet || go get golang.org/x/tools/cmd/vet
- go vet
- go test -v
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# DeVo Changelog

## 0.7.0 (2016-02-03)
- Initial release on GitHub
19 changes: 19 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Copyright (c) 2016 Bob Ziuchkovski

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
51 changes: 51 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
[![Build Status](https://travis-ci.org/ziuchkovski/devo.svg?branch=master)](https://travis-ci.org/ziuchkovski/devo)
[![Coverage](http://gocover.io/_badge/github.com/ziuchkovski/devo?0)](http://gocover.io/github.com/ziuchkovski/devo)
[![Report Card](http://goreportcard.com/badge/ziuchkovski/devo)](http://goreportcard.com/report/ziuchkovski/devo)
[![GoDoc](https://godoc.org/github.com/ziuchkovski/devo?status.svg)](https://godoc.org/github.com/ziuchkovski/devo)

# DeVo

## Overview

DeVo decrypts TiVo files. It supports both mpeg-ps and mpeg-ts input formats.
Decrypting requires the correct media access key (MAK) from the source TiVo device.
DeVo is intended for personal/educational use only. Decrypted files must NOT be distributed.
Piracy is not condoned!

## Usage

`devo -m [MAK] -i [INPUT] -o [OUTPUT]`

If the output file is garbled, double-check the provided access key.
DeVo makes no attempt to detect bogus access keys.

## Library

DeVo is implemented in pure (Go)[https://golang.org/] and can be used as a library.
Please see the [godocs](https://godoc.org/github.com/ziuchkovski/devo) for details.

## Authors

Bob Ziuchkovski (@ziuchkovski)

## License (MIT)

Copyright (c) 2016 Bob Ziuchkovski

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
63 changes: 63 additions & 0 deletions cipherpool.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright (c) 2016 Bob Ziuchkovski
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package devo

import (
"crypto/sha1"
"github.com/ziuchkovski/turing"
)

type cipherHandle struct {
id uint8
confounder [3]byte
}

type cipherPool struct {
mak string // Media access key (MAK) from TiVo unit
iv []byte // Initialization vector (IV) from file metadata
ciphers map[cipherHandle]*turing.Cipher
}

func newCipherPool(mak string, iv []byte) *cipherPool {
return &cipherPool{
mak: mak,
iv: iv,
ciphers: make(map[cipherHandle]*turing.Cipher),
}
}

func (pool *cipherPool) getCipher(id uint8, confounder [3]byte) *turing.Cipher {
handle := cipherHandle{id: id, confounder: confounder}
c, present := pool.ciphers[handle]
if !present {
basekey := sha1.Sum(append([]byte(pool.mak), pool.iv...))
derivedkey := sha1.Sum(append(basekey[:16], handle.id))
derivediv := sha1.Sum(append(basekey[:16], handle.id, handle.confounder[0], handle.confounder[1], handle.confounder[2]))

var err error
c, err = turing.NewCipher(derivedkey[:], derivediv[:])
if err != nil {
panic(err)
}
pool.ciphers[handle] = c
}
return c
}
99 changes: 99 additions & 0 deletions cmd/devo/legacy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// +build !go1.5

// Copyright (c) 2016 Bob Ziuchkovski
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package main

import (
"fmt"
"github.com/ziuchkovski/devo"
"github.com/ziuchkovski/writ"
"io"
"os"
"regexp"
"runtime"
)

const (
usage = "Usage: devo [OPTION]..."
header = `
DeVo decrypts TiVo recordings. It is intended for personal/educational use only.
Decrypted files must NOT be distributed. Piracy is NOT condoned!`
footer = "DeVo home page: https://github.com/ziuchkovski/devo"
)

type config struct {
Input io.Reader `option:"i, input" placeholder:"FILE" description:"The encrypted input TiVo file"`
Output io.WriteCloser `option:"o, output" placeholder:"FILE" description:"The decrypted output video file"`
AccessKey string `option:"m, mak" placeholder:"MAK" description:"The 10-digit media access key (MAK) from your TiVo"`
HelpFlag bool `flag:"h, help" description:"Display this help text and exit"`
VersionFlag bool `flag:"version" description:"Display version information and exit"`
}

func (c config) validate() error {
if c.Input == nil {
return fmt.Errorf("-i/--input must be specified")
}
if c.Output == nil {
return fmt.Errorf("-o/--output must be specified")
}
if c.AccessKey == "" {
return fmt.Errorf("-m/--mak is required")
}
if !regexp.MustCompile("^\\d{10}$").MatchString(c.AccessKey) {
return fmt.Errorf("-m/--mak must be a 10 digit value")
}
return nil
}

func main() {
config := &config{}
cmd := writ.New("devo", config)
cmd.Help.Usage = usage
cmd.Help.Header = header
cmd.Help.Footer = footer
_, positional, err := cmd.Decode(os.Args[1:])

if err != nil || config.HelpFlag {
cmd.ExitHelp(err)
}
if config.VersionFlag {
fmt.Fprintf(os.Stdout, "DeVo version %d.%d.%d\nCompiled with %s\n", devo.Version.Major, devo.Version.Minor, devo.Version.Patch, runtime.Version())
os.Exit(0)
}
if len(positional) != 0 {
cmd.ExitHelp(fmt.Errorf("too many arguments provided"))
}
err = config.validate()
if err != nil {
cmd.ExitHelp(err)
}

defer config.Output.Close()
check(devo.Decrypt(config.Output, config.Input, config.AccessKey))
}

func check(err error) {
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
os.Exit(1)
}
}
117 changes: 117 additions & 0 deletions cmd/devo/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// +build go1.5

// Copyright (c) 2016 Bob Ziuchkovski
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package main

import (
"fmt"
"github.com/ziuchkovski/devo"
"github.com/ziuchkovski/writ"
"io"
"os"
"regexp"
"runtime"
"runtime/pprof"
"runtime/trace"
)

const (
usage = "Usage: devo [OPTION]..."
header = `
DeVo decrypts TiVo recordings. It is intended for personal/educational use only.
Decrypted files must NOT be distributed. Piracy is NOT condoned!`
footer = "DeVo home page: https://github.com/ziuchkovski/devo"
)

type config struct {
Input io.Reader `option:"i, input" placeholder:"FILE" description:"The encrypted input TiVo file"`
Output io.WriteCloser `option:"o, output" placeholder:"FILE" description:"The decrypted output video file"`
TraceOutput io.WriteCloser `option:"t, trace"`
ProfileOutput io.WriteCloser `option:"p, profile"`
AccessKey string `option:"m, mak" placeholder:"MAK" description:"The 10-digit media access key (MAK) from your TiVo"`
HelpFlag bool `flag:"h, help" description:"Display this help text and exit"`
VersionFlag bool `flag:"version" description:"Display version information and exit"`
}

func (c config) validate() error {
if c.Input == nil {
return fmt.Errorf("-i/--input must be specified")
}
if c.Output == nil {
return fmt.Errorf("-o/--output must be specified")
}
if c.AccessKey == "" {
return fmt.Errorf("-m/--mak is required")
}
if !regexp.MustCompile("^\\d{10}$").MatchString(c.AccessKey) {
return fmt.Errorf("-m/--mak must be a 10 digit value")
}
return nil
}

func main() {
config := &config{}
cmd := writ.New("devo", config)
cmd.Help.Usage = usage
cmd.Help.Header = header
cmd.Help.Footer = footer
_, positional, err := cmd.Decode(os.Args[1:])

if err != nil || config.HelpFlag {
cmd.ExitHelp(err)
}
if config.VersionFlag {
fmt.Fprintf(os.Stdout, "DeVo version %d.%d.%d\nCompiled with %s\n", devo.Version.Major, devo.Version.Minor, devo.Version.Patch, runtime.Version())
os.Exit(0)
}
if len(positional) != 0 {
cmd.ExitHelp(fmt.Errorf("too many arguments provided"))
}
err = config.validate()
if err != nil {
cmd.ExitHelp(err)
}

if config.TraceOutput != nil {
defer config.TraceOutput.Close()
err = trace.Start(config.TraceOutput)
check(err)
defer trace.Stop()
}

if config.ProfileOutput != nil {
defer config.ProfileOutput.Close()
err = pprof.StartCPUProfile(config.ProfileOutput)
check(err)
defer pprof.StopCPUProfile()
}

defer config.Output.Close()
check(devo.Decrypt(config.Output, config.Input, config.AccessKey))
}

func check(err error) {
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
os.Exit(1)
}
}
Loading

0 comments on commit ba8d395

Please sign in to comment.