|
|
@ -50,6 +50,26 @@ EXIV2_RCSID("@(#) $Id$")
|
|
|
|
#include <cassert>
|
|
|
|
#include <cassert>
|
|
|
|
#include <cstring>
|
|
|
|
#include <cstring>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// *****************************************************************************
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
using namespace Exiv2;
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
|
|
|
@brief Decrypt Nikon data (Ref [4])
|
|
|
|
|
|
|
|
@param pData Pointer to the data to decrypt
|
|
|
|
|
|
|
|
@param size Size of the data buffer
|
|
|
|
|
|
|
|
@return 0 if successful (and decrypted data in buf)
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
int decryptNikonData(byte* pData, uint32_t size, const ExifData& exifData);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
|
|
|
@brief Decrypt Nikon data (Ref [4], [7])
|
|
|
|
|
|
|
|
@param pData Pointer to the data to decrypt
|
|
|
|
|
|
|
|
@param size Size of the data buffer
|
|
|
|
|
|
|
|
@param count Shutter count key
|
|
|
|
|
|
|
|
@param serial Serial number key
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
void decrypt(byte* pData, uint32_t size, uint32_t count, uint32_t serial);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// *****************************************************************************
|
|
|
|
// *****************************************************************************
|
|
|
|
// class member definitions
|
|
|
|
// class member definitions
|
|
|
|
namespace Exiv2 {
|
|
|
|
namespace Exiv2 {
|
|
|
@ -621,8 +641,8 @@ namespace Exiv2 {
|
|
|
|
TagInfo(0x009f, "0x009f", "0x009f",
|
|
|
|
TagInfo(0x009f, "0x009f", "0x009f",
|
|
|
|
N_("Unknown"),
|
|
|
|
N_("Unknown"),
|
|
|
|
nikon3IfdId, makerTags, signedShort, printValue),
|
|
|
|
nikon3IfdId, makerTags, signedShort, printValue),
|
|
|
|
TagInfo(0x00a0, "SerialNumber", N_("Serial Number"),
|
|
|
|
TagInfo(0x00a0, "SerialNO", N_("Serial NO"),
|
|
|
|
N_("Camera serial number"),
|
|
|
|
N_("Camera serial number, usually starts with \"NO= \""),
|
|
|
|
nikon3IfdId, makerTags, asciiString, printValue),
|
|
|
|
nikon3IfdId, makerTags, asciiString, printValue),
|
|
|
|
TagInfo(0x00a2, "ImageDataSize", N_("Image Data Size"),
|
|
|
|
TagInfo(0x00a2, "ImageDataSize", N_("Image Data Size"),
|
|
|
|
N_("Image data size"),
|
|
|
|
N_("Image data size"),
|
|
|
@ -910,7 +930,7 @@ namespace Exiv2 {
|
|
|
|
|
|
|
|
|
|
|
|
std::ostream& Nikon3MakerNote::print0x0098(std::ostream& os,
|
|
|
|
std::ostream& Nikon3MakerNote::print0x0098(std::ostream& os,
|
|
|
|
const Value& value,
|
|
|
|
const Value& value,
|
|
|
|
const ExifData*)
|
|
|
|
const ExifData* metadata)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
#ifdef EXV_HAVE_LENSDATA
|
|
|
|
#ifdef EXV_HAVE_LENSDATA
|
|
|
|
//#-----------------------------------------
|
|
|
|
//#-----------------------------------------
|
|
|
@ -1309,10 +1329,13 @@ namespace Exiv2 {
|
|
|
|
else if (0 == memcmp(lens.pData_, "0101", 4)) {
|
|
|
|
else if (0 == memcmp(lens.pData_, "0101", 4)) {
|
|
|
|
idx = 11;
|
|
|
|
idx = 11;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (0 == memcmp(lens.pData_, "0201", 4)) {
|
|
|
|
else if ( 0 == memcmp(lens.pData_, "0201", 4)
|
|
|
|
// Todo: decrypt(lens.pData_ + 4, lens.size_ - 4);
|
|
|
|
|| 0 == memcmp(lens.pData_, "0202", 4)) {
|
|
|
|
|
|
|
|
if (metadata) {
|
|
|
|
// The decrypt algorithm requires access to serial number
|
|
|
|
// The decrypt algorithm requires access to serial number
|
|
|
|
// and shutter count tags
|
|
|
|
// and shutter count tags
|
|
|
|
|
|
|
|
decryptNikonData(lens.pData_ + 4, lens.size_ - 4, *metadata);
|
|
|
|
|
|
|
|
}
|
|
|
|
idx = 11;
|
|
|
|
idx = 11;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (idx == 0 || lens.size_ < idx + 7) {
|
|
|
|
if (idx == 0 || lens.size_ < idx + 7) {
|
|
|
@ -1339,3 +1362,85 @@ namespace Exiv2 {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace Exiv2
|
|
|
|
} // namespace Exiv2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// *****************************************************************************
|
|
|
|
|
|
|
|
// local definitions
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int decryptNikonData(byte* pData, uint32_t size, const ExifData& exifData)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
ExifKey key("Exif.Nikon3.ShutterCount");
|
|
|
|
|
|
|
|
ExifData::const_iterator pos = exifData.findKey(key);
|
|
|
|
|
|
|
|
if (pos == exifData.end() || pos->count() == 0) return 1;
|
|
|
|
|
|
|
|
uint32_t count = static_cast<uint32_t>(pos->toLong());
|
|
|
|
|
|
|
|
key = ExifKey("Exif.Nikon3.SerialNumber");
|
|
|
|
|
|
|
|
pos = exifData.findKey(key);
|
|
|
|
|
|
|
|
if (pos == exifData.end() || pos->count() == 0) return 2;
|
|
|
|
|
|
|
|
bool ok(false);
|
|
|
|
|
|
|
|
uint32_t serial = stringTo<uint32_t>(pos->toString(), ok);
|
|
|
|
|
|
|
|
if (!ok) {
|
|
|
|
|
|
|
|
key = ExifKey("Exif.Image.Model");
|
|
|
|
|
|
|
|
pos = exifData.findKey(key);
|
|
|
|
|
|
|
|
if (pos == exifData.end() || pos->count() == 0) return 3;
|
|
|
|
|
|
|
|
std::string model = pos->toString();
|
|
|
|
|
|
|
|
if (model.find("D50") != std::string::npos) {
|
|
|
|
|
|
|
|
serial = 0x22;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else {
|
|
|
|
|
|
|
|
serial = 0x60;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
decrypt(pData, size, count, serial);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void decrypt(byte* pData, uint32_t size, uint32_t count, uint32_t serial)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
static const byte xlat[2][256] = {
|
|
|
|
|
|
|
|
{ 0xc1,0xbf,0x6d,0x0d,0x59,0xc5,0x13,0x9d,0x83,0x61,0x6b,0x4f,0xc7,0x7f,0x3d,0x3d,
|
|
|
|
|
|
|
|
0x53,0x59,0xe3,0xc7,0xe9,0x2f,0x95,0xa7,0x95,0x1f,0xdf,0x7f,0x2b,0x29,0xc7,0x0d,
|
|
|
|
|
|
|
|
0xdf,0x07,0xef,0x71,0x89,0x3d,0x13,0x3d,0x3b,0x13,0xfb,0x0d,0x89,0xc1,0x65,0x1f,
|
|
|
|
|
|
|
|
0xb3,0x0d,0x6b,0x29,0xe3,0xfb,0xef,0xa3,0x6b,0x47,0x7f,0x95,0x35,0xa7,0x47,0x4f,
|
|
|
|
|
|
|
|
0xc7,0xf1,0x59,0x95,0x35,0x11,0x29,0x61,0xf1,0x3d,0xb3,0x2b,0x0d,0x43,0x89,0xc1,
|
|
|
|
|
|
|
|
0x9d,0x9d,0x89,0x65,0xf1,0xe9,0xdf,0xbf,0x3d,0x7f,0x53,0x97,0xe5,0xe9,0x95,0x17,
|
|
|
|
|
|
|
|
0x1d,0x3d,0x8b,0xfb,0xc7,0xe3,0x67,0xa7,0x07,0xf1,0x71,0xa7,0x53,0xb5,0x29,0x89,
|
|
|
|
|
|
|
|
0xe5,0x2b,0xa7,0x17,0x29,0xe9,0x4f,0xc5,0x65,0x6d,0x6b,0xef,0x0d,0x89,0x49,0x2f,
|
|
|
|
|
|
|
|
0xb3,0x43,0x53,0x65,0x1d,0x49,0xa3,0x13,0x89,0x59,0xef,0x6b,0xef,0x65,0x1d,0x0b,
|
|
|
|
|
|
|
|
0x59,0x13,0xe3,0x4f,0x9d,0xb3,0x29,0x43,0x2b,0x07,0x1d,0x95,0x59,0x59,0x47,0xfb,
|
|
|
|
|
|
|
|
0xe5,0xe9,0x61,0x47,0x2f,0x35,0x7f,0x17,0x7f,0xef,0x7f,0x95,0x95,0x71,0xd3,0xa3,
|
|
|
|
|
|
|
|
0x0b,0x71,0xa3,0xad,0x0b,0x3b,0xb5,0xfb,0xa3,0xbf,0x4f,0x83,0x1d,0xad,0xe9,0x2f,
|
|
|
|
|
|
|
|
0x71,0x65,0xa3,0xe5,0x07,0x35,0x3d,0x0d,0xb5,0xe9,0xe5,0x47,0x3b,0x9d,0xef,0x35,
|
|
|
|
|
|
|
|
0xa3,0xbf,0xb3,0xdf,0x53,0xd3,0x97,0x53,0x49,0x71,0x07,0x35,0x61,0x71,0x2f,0x43,
|
|
|
|
|
|
|
|
0x2f,0x11,0xdf,0x17,0x97,0xfb,0x95,0x3b,0x7f,0x6b,0xd3,0x25,0xbf,0xad,0xc7,0xc5,
|
|
|
|
|
|
|
|
0xc5,0xb5,0x8b,0xef,0x2f,0xd3,0x07,0x6b,0x25,0x49,0x95,0x25,0x49,0x6d,0x71,0xc7 },
|
|
|
|
|
|
|
|
{ 0xa7,0xbc,0xc9,0xad,0x91,0xdf,0x85,0xe5,0xd4,0x78,0xd5,0x17,0x46,0x7c,0x29,0x4c,
|
|
|
|
|
|
|
|
0x4d,0x03,0xe9,0x25,0x68,0x11,0x86,0xb3,0xbd,0xf7,0x6f,0x61,0x22,0xa2,0x26,0x34,
|
|
|
|
|
|
|
|
0x2a,0xbe,0x1e,0x46,0x14,0x68,0x9d,0x44,0x18,0xc2,0x40,0xf4,0x7e,0x5f,0x1b,0xad,
|
|
|
|
|
|
|
|
0x0b,0x94,0xb6,0x67,0xb4,0x0b,0xe1,0xea,0x95,0x9c,0x66,0xdc,0xe7,0x5d,0x6c,0x05,
|
|
|
|
|
|
|
|
0xda,0xd5,0xdf,0x7a,0xef,0xf6,0xdb,0x1f,0x82,0x4c,0xc0,0x68,0x47,0xa1,0xbd,0xee,
|
|
|
|
|
|
|
|
0x39,0x50,0x56,0x4a,0xdd,0xdf,0xa5,0xf8,0xc6,0xda,0xca,0x90,0xca,0x01,0x42,0x9d,
|
|
|
|
|
|
|
|
0x8b,0x0c,0x73,0x43,0x75,0x05,0x94,0xde,0x24,0xb3,0x80,0x34,0xe5,0x2c,0xdc,0x9b,
|
|
|
|
|
|
|
|
0x3f,0xca,0x33,0x45,0xd0,0xdb,0x5f,0xf5,0x52,0xc3,0x21,0xda,0xe2,0x22,0x72,0x6b,
|
|
|
|
|
|
|
|
0x3e,0xd0,0x5b,0xa8,0x87,0x8c,0x06,0x5d,0x0f,0xdd,0x09,0x19,0x93,0xd0,0xb9,0xfc,
|
|
|
|
|
|
|
|
0x8b,0x0f,0x84,0x60,0x33,0x1c,0x9b,0x45,0xf1,0xf0,0xa3,0x94,0x3a,0x12,0x77,0x33,
|
|
|
|
|
|
|
|
0x4d,0x44,0x78,0x28,0x3c,0x9e,0xfd,0x65,0x57,0x16,0x94,0x6b,0xfb,0x59,0xd0,0xc8,
|
|
|
|
|
|
|
|
0x22,0x36,0xdb,0xd2,0x63,0x98,0x43,0xa1,0x04,0x87,0x86,0xf7,0xa6,0x26,0xbb,0xd6,
|
|
|
|
|
|
|
|
0x59,0x4d,0xbf,0x6a,0x2e,0xaa,0x2b,0xef,0xe6,0x78,0xb6,0x4e,0xe0,0x2f,0xdc,0x7c,
|
|
|
|
|
|
|
|
0xbe,0x57,0x19,0x32,0x7e,0x2a,0xd0,0xb8,0xba,0x29,0x00,0x3c,0x52,0x7d,0xa8,0x49,
|
|
|
|
|
|
|
|
0x3b,0x2d,0xeb,0x25,0x49,0xfa,0xa3,0xaa,0x39,0xa7,0xc5,0xa7,0x50,0x11,0x36,0xfb,
|
|
|
|
|
|
|
|
0xc6,0x67,0x4a,0xf5,0xa5,0x12,0x65,0x7e,0xb0,0xdf,0xaf,0x4e,0xb3,0x61,0x7f,0x2f }
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
byte key = 0;
|
|
|
|
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
|
|
|
|
|
|
key ^= (count >> (i*8)) & 0xff;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
byte ci = xlat[0][serial & 0xff];
|
|
|
|
|
|
|
|
byte cj = xlat[1][key];
|
|
|
|
|
|
|
|
byte ck = 0x60;
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < size; ++i) {
|
|
|
|
|
|
|
|
cj += ci * ck++;
|
|
|
|
|
|
|
|
pData[i] ^= cj;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|