2024-04-29

Navigation

Skip Navigation Links

Hash algorithms

Asymmetric Algorithms

Symmetric Cipher Algorithms

Encoding Algorithms

Compression Algorithms

Pseudo Random Number Algorithms

Steganography

Library Wrappers

String Comparison

Others

Syntax highlighting by Prism
PBCrypto.com Mirror

Hide text in BMP image data

Algorithm creator(s)

n/a


PB author(s)

Wayne Diamond


Description

Demonstration of a simple, common image watermarking technique. The least significant bit (LSB) of each byte in the image data is used to store a hidden message.


Note

The first PowerBASIC steganographic example, this is a simple demonstration of just one of many steganographic techniques that can be applied to images.


Source

https://forum.powerbasic.com/forum/user-to-user-discussions/source-code/24148-steganography-hide-a-message-inside-a-bitmap-image?t=23511


See also

n/a


Source Code

Download source code file steg-bmpdata.bas (Right-click -> "Save as ...")

Data modification sample:
 Before: 000A0A170A0A0A0A0A0A0A0A0A0A0A170C080A010F010B6A4D630215060D0B0E080C0C0808171F4E310C13040834010403150911000F040504061E0904
 After : 010B0B170A0A0A0A0B0A0B0B0A0A0B160D080A010F010B6A4C620214060D0A0E080C0D0809171F4E310C13040835010403150810010F050404061F0805
          ^ ^ ^           ^   ^ ^     ^ ^ ^               ^ ^   ^     ^       ^   ^                 ^         ^ ^ ^   ^ ^     ^ ^ ^
 
'#########################################################
#COMPILE EXE
'ready-to-compile in PBCC
'just delete WAITKEY$ and replace STDOUT with MSGBOX to compile in PBDLL/PBWIN
'modify the PBMAIN function so that it points at a valid BMP before compiling. 
 
TYPE BITMAP_HEADER
 'Based on this BMP specification:
 ' http://www.wotsit.org/filestore/bmpfrmat.zip 
 wIdentifier AS WORD
 dwFilesize AS DWORD
 dwReserved AS DWORD
 dwDataOffset AS DWORD
 dwHeaderSize AS DWORD
 dwWidth AS DWORD
 dwHeight AS DWORD
 wPlanes AS WORD
 wBitsPerPixel AS WORD
 dwCompression AS DWORD
 dwDataSize AS DWORD
 dwHResolution AS DWORD
 dwVResolution AS DWORD
 dwColors AS DWORD
 dwImportantColors AS DWORD
END TYPE 
 
'#########################################################
SUB SaveMessage(sFile AS STRING, sPlainText AS STRING)
ON ERROR RESUME NEXT
LOCAL f AS LONG, char AS BYTE, char2 AS BYTE, x AS BYTE, DataPos AS LONG, tmp AS LONG
LOCAL bmp AS BITMAP_HEADER, sData AS STRING, sText AS STRING
IF LEN(sPlainText) > 255 THEN
    STDOUT "Maximum message length in this version is 255 characters"
    EXIT SUB
END IF
sText = CHR$(LEN(sPlainText)) & sPlainText  'first byte of sText = len of sText
f = FREEFILE
OPEN sFile FOR BINARY ACCESS READ LOCK SHARED AS #f
 GET #f, 1, bmp
 sData = SPACE$(bmp.dwDataSize)
 GET #f, bmp.dwDataOffset, sData  'fill sData with the data from dwDataOffset
CLOSE #f
STDOUT "This file can hold a maximum of " & TRIM$(STR$(CINT(bmp.dwDatasize / 8))) & " plaintext characters"
DataPos = 1
FOR f = 1 TO LEN(sText)
    char = ASC(MID$(sText, f, 1))
    FOR x = 0 TO 7
     char2 = ASC(MID$(sData, DataPos,1))
     tmp = BIT(char, x)
     IF tmp = 0 THEN
        BIT RESET char2, 0
     ELSE
        BIT SET char2, 0
     END IF
     MID$(sData, DataPos,1) = CHR$(char2)
     DataPos = DataPos + 1
    NEXT x
NEXT f
f = FREEFILE
OPEN sFile FOR BINARY ACCESS WRITE LOCK SHARED AS #f
 PUT #f, bmp.dwDataOffset, sData
CLOSE #f
END SUB
 
'#########################################################
SUB ShowMessage (sFile AS STRING)
ON ERROR RESUME NEXT
LOCAL f AS LONG, I AS LONG, sData AS STRING, sOut AS STRING
LOCAL tmp AS LONG, DataPos AS LONG, char AS BYTE, char2 AS BYTE, bmp AS BITMAP_HEADER
f = FREEFILE
OPEN sFile FOR BINARY ACCESS READ LOCK SHARED AS #f
 GET #f, 1, bmp
 sData = SPACE$(bmp.dwDataSize)
 GET #f, bmp.dwDataOffset, sData  'fill sData with the data from dwDataOffset
CLOSE #f
char = 0
FOR I = 1 TO 8
 char = ASC(MID$(sData, i, 1))
 tmp = BIT(char, 0)
 IF tmp = 0 THEN
     BIT RESET char2, I - 1
 ELSE
     BIT SET char2, I - 1
 END IF
NEXT I
STDOUT "Message size = " & STR$(char2)
sOut = SPACE$(char2)
DataPos = 9
FOR I = 1 TO char2
 char2 = 0
 FOR f = 0 TO 7
  char = ASC(MID$(sData, DataPos, 1))
  tmp = BIT(char, 0)
  IF tmp = 0 THEN
      BIT RESET char2, f
  ELSE
      BIT SET char2, f
  END IF
  DataPos = DataPos + 1
 NEXT f
 MID$(sOut, I, 1) = CHR$(char2)
NEXT I
STDOUT "Extracted message = " & sOut
END SUB 
 
'#########################################################
FUNCTION PBMAIN() AS LONG
ON ERROR RESUME NEXT
'create the bitmap to use for encoding/decoding messages
KILL "d:\temp\steg.bmp"
FILECOPY "d:\winnt\coffee bean.bmp", "d:\temp\steg.bmp" 
'## Encode a message
SaveMessage "d:\temp\steg.bmp", "My test message" 
'## Decode the message
ShowMessage "d:\temp\steg.bmp"
WAITKEY$
END FUNCTION

Mirror provided by Knuth Konrad