Skip to content

Commit

Permalink
Merge branch 'release/v2.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
auyer committed Apr 27, 2019
2 parents 35d9466 + d7762d8 commit 2664780
Show file tree
Hide file tree
Showing 5 changed files with 255 additions and 108 deletions.
63 changes: 38 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,16 @@ This library is inspired by [Stego by EthanWelsh](https://github.com/EthanWelsh/

## Installation
```go
go get -u github.com/auyer/steganography
go get -u gopkg.in/auyer/steganography.v2
```

## Demonstration

| Original | Encoded |
| Original |Encoded |
| -------------------- | ------------------|
| ![Original File](examples/stegosaurus.png) | ![Encoded File](examples/encoded_stegosaurus.png)
| 79,955 bytes | 80,629 bytes |
| ![Original File](examples/stegosaurus.png) | ![Encoded File](examples/encoded_stegosaurus.png)

The second image contains the first paragaph of the description of a stegosaurus on [Wikipidia](https://en.wikipedia.org/wiki/Stegosaurus), also available in [examples/message.txt](examples/message.txt) as an example.
The second image contains the first paragaph of the description of a stegosaurus on [Wikipidia](https://en.wikipedia.org/wiki/Stegosaurus), also available in [examples/message.txt](https://raw.githubusercontent.com/auyer/steganography/master/examples/message.txt) as an example.

------
Getting Started
Expand All @@ -34,56 +33,70 @@ import (
"image"
"io/ioutil"

"github.com/auyer/steganography"
"gopkg.in/auyer/steganography.v2"
)
```

Encode
------
Write mode is used to take a message and embed it into an image file using LSB steganography in order to produce a secret image file that will contain your message.

Note that the minnimum image size is 24 pixels for one byte. For each additional byte, it is necessary 3 more pixels.

```go
inFile, _ := os.Open(file_path) // reads the File
img, _, err := image.Decode(reader) // Decodes image
encodedImg := steganography.EncodeString(message, img) // Encode the message into the provided image file
outFile, _ := os.Create(pictureOutputFile) // Creates the new file
bufio.NewWriter(outFile).Write(encodedImg.Bytes()) // writes file into disk
inFile, _ := os.Open("input_file.png") // opening file
reader := bufio.NewReader(inFile) // buffer reader
img, _, _ := image.Decode(reader) // decoding to golang's image.Image

w := new(bytes.Buffer) // buffer that will recieve the results
err := steganography.Encode(w, img, "message") // Encode the message into the image
if err != nil {
log.Printf("Error Encoding file %v", err)
return
}
outFile, _ := os.Create("out_file.png") // create file
w.WriteTo(outFile) // write buffer to it
outFile.Close()
```

Size of Message
------
Length mode can be used in order to preform a preliminary check on the carrier image in order to deduce how large of a file it can store.

```go
sizeOfMessage := steganography.GetSizeOfMessageFromImage(img) // retrieves the size of the encoded message
sizeOfMessage := GetMessageSizeFromImage(img) // retrieves the size of the encoded message
```

Decode
-----
Read mode is used to read an image that has been encoded using LSB steganography, and extract the hidden message from that image.

```go
inFile, _ := os.Open(file_path) // reads the File
img, _, err := image.Decode(bufio.NewReader(inFile)) // Decodes image
sizeOfMessage := steganography.GetSizeOfMessageFromImage(img) // retrieves the size of the encoded message
inFile, _ := os.Open(encodedInputFile) // opening file
inFile.Close()

msg := steganography.DecodeMessageFromPicture(4, sizeOfMessage, img) // Decodes the message from file
```
reader := bufio.NewReader(inFile) // buffer reader
img, _, _ := image.Decode(reader) // decoding to golang's image.Image

sizeOfMessage := GetMessageSizeFromImage(img) // retrieving message size to decode in the next line

msg := Decode(sizeOfMessage, img) // decoding the message from the file
fmt.Println(string(msg))

Open Image From Path
-----
If you do not want to deal with opening the image file in your code, there is a helper function for you. It will do the dirty job and return the image in a way usable by the encode and decode fucntions.
```go
img, err := OpenImageFromPath(imagePath)
if err != nil {
log.Printf("Error opening or Decoding file %s: %v", imagePath, err)
}
```

Complete Example
------
For a complete example, see the [examples/stego.go](examples/stego.go) file. It is a command line app based on the original fork of this repository, but modifid to use the Steganography library.

----
### V1 Compatibility:

It is highly recommended for past users to upgrade to v2, but old users can still use it with:
```
import "gopkg.in/auyer/steganography.v1"
```

-----
### Attributions
- Stegosaurus Picture By Matt Martyniuk - Own work, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=42215661
28 changes: 24 additions & 4 deletions examples/stego.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"bufio"
"bytes"
"flag"
"fmt"
"image"
Expand Down Expand Up @@ -37,6 +38,21 @@ func init() {
flag.Parse()
}

// OpenImageFromPath returns a image.Image from a file path. A helper function to deal with decoding the image into a usable format. This method is optional.
func OpenImageFromPath(filename string) (image.Image, error) {
inFile, err := os.Open(filename)
if err != nil {
return nil, err
}
defer inFile.Close()
reader := bufio.NewReader(inFile)
img, _, err := image.Decode(reader)
if err != nil {
return nil, err
}
return img, nil
}

func main() {
if encode {
message, err := ioutil.ReadFile(messageInputFile) // Read the message from the message file (alternative to os.Open )
Expand All @@ -56,8 +72,12 @@ func main() {
if err != nil {
log.Fatalf("Error opening file %v", err)
}
encodedImg := steganography.EncodeString(message, img) // Calls library and Encodes the message into a new buffer
outFile, err := os.Create(pictureOutputFile) // Creates file to write the message into
encodedImg := new(bytes.Buffer)
err = steganography.Encode(encodedImg, img, message) // Calls library and Encodes the message into a new buffer
if err != nil {
log.Fatalf("Error encoding message into file %v", err)
}
outFile, err := os.Create(pictureOutputFile) // Creates file to write the message into
if err != nil {
log.Fatalf("Error creating file %s: %v", pictureOutputFile, err)
}
Expand All @@ -77,9 +97,9 @@ func main() {
log.Fatal("error decoding file", img)
}

sizeOfMessage := steganography.GetSizeOfMessageFromImage(img) // Uses the library to check the message size
sizeOfMessage := steganography.GetMessageSizeFromImage(img) // Uses the library to check the message size

msg := steganography.DecodeMessageFromPicture(4, sizeOfMessage, img) // Read the message from the picture file
msg := steganography.Decode(sizeOfMessage, img) // Read the message from the picture file

// if the user specifies a location to write the message to...
if messageOutputFile != "" {
Expand Down
31 changes: 31 additions & 0 deletions examples/stego_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package main

import (
"image"
"log"
"testing"
)

var rawInputFile = "./stegosaurus.png"
var encodedInputFile = "./encoded_stegosaurus.png"

func TestOpenImageFromPath(t *testing.T) {
img, err := OpenImageFromPath(rawInputFile)
if err != nil {
log.Printf("Error opening or Decoding file %s: %v", rawInputFile, err)
t.FailNow()
}
if (img.Bounds().Bounds() != image.Rectangle{image.Point{0, 0}, image.Point{1195, 642}}) {
log.Printf("Image has wrong size")
t.FailNow()

}
}

func TestEmptyPathHelperFunction(t *testing.T) {
_, err := OpenImageFromPath(" ")
if err == nil {
log.Print("Empty path given, err could not be nil.")
t.FailNow()
}
}
Loading

0 comments on commit 2664780

Please sign in to comment.