BlackBerry 10,3DES-ECB实施

时间:2017-11-19 09:01:15

标签: php openssl blackberry-10 blackberry-cascades 3des

简介

我的bb10应用已发送3DES-ECB - 加密数据到后端(PHP)

代码

PHP后端

public static function encrypt3Des($data, $key)
{
    //Generate a key from a hash
    $key = md5(utf8_encode($key), true);
    //Take first 8 bytes of $key and append them to the end of $key.
    $key .= substr($key, 0, 8);
    //Pad for PKCS7
    $blockSize = mcrypt_get_block_size('tripledes', 'ecb');
    $len = strlen($data);
    $pad = $blockSize - ($len % $blockSize);
    $data = $data.str_repeat(chr($pad), $pad);
    //Encrypt data
    $encData = mcrypt_encrypt('tripledes', $key, $data, 'ecb');
    return base64_encode($encData);
}

public static function decrypt3Des($data, $secret)
{
    //Generate a key from a hash
    $key = md5(utf8_encode($secret), true);
    //Take first 8 bytes of $key and append them to the end of $key.
    $key .= substr($key, 0, 8);
    $data = base64_decode($data);
    $data = mcrypt_decrypt('tripledes', $key, $data, 'ecb');
    $block = mcrypt_get_block_size('tripledes', 'ecb');
    $len = strlen($data);
    $pad = ord($data[$len-1]);
    return substr($data, 0, strlen($data) - $pad);
}

Blackberry 10客户端

/// cipherservice.hpp ///

#pragma once

#include <QObject>

#include <hudes.h>
#include <hugse56.h>

class CipherService : public QObject {
    Q_OBJECT
public:

    virtual ~CipherService();
    CipherService(QString key);

    QString encryptTDES(QString message);
    QString decryptTDES(QString message);

private:
    void initCipher(QString key);
    void destroyCipher();

    sb_GlobalCtx huGlobalContext;
    sb_Context huContext;
    sb_Key huKey;
    sb_Params huParams;
};

/// cipherservice.cpp ///

#include "cipherservice.hpp"

#include <huctx.h>

#define TO_HEXSTR(code) ("0x" + QString("%1").arg(code, 0, 16).toUpper())

CipherService::CipherService(QString key)
    : QObject() {
    initCipher(key);
}

CipherService::~CipherService() {
    destroyCipher();
}

void CipherService::initCipher(QString key) {
    int rc = hu_GlobalCtxCreateDefault(&huGlobalContext);
    LOGD << "hu_GlobalCtxCreateDefault return code = " << TO_HEXSTR(rc);

    rc = hu_RegisterSbg56DES(huGlobalContext);
    LOGD << "hu_RegisterSbg56DES return code = " << TO_HEXSTR(rc);

    rc = hu_InitSbg56(huGlobalContext);
    LOGD << "hu_InitSbg56 return code = " << TO_HEXSTR(rc) << " (0xF00D means already initialized so ignore it)";

    rc = hu_DESParamsCreate(USED_SB_DES, SB_DES_ECB, SB_DES_PARITY_OFF, SB_DES_WEAK_KEY_OFF,
            NULL, NULL, &huParams, huGlobalContext);
    LOGD << "hu_DESParamsCreate return code = " << TO_HEXSTR(rc);

    QByteArray resultKey = QCryptographicHash::hash(key.toUtf8().constData(), QCryptographicHash::Md5);
    resultKey.append(resultKey.mid(0, 8));

    LOGD << "key=" << resultKey.toBase64();

    unsigned char* keyBuf = reinterpret_cast<unsigned char*>(resultKey.data());
    size_t keyBufLen = SB_DES_KEY_SIZE;
    rc = hu_DESKeySet(huParams, keyBufLen, keyBuf, keyBufLen, keyBuf, keyBufLen, keyBuf, &huKey, huGlobalContext);
    LOGD << "hu_DESKeySet return code = " << TO_HEXSTR(rc);

    const unsigned char iv[SB_DES_IV_SIZE] = {0};
    rc = hu_DESBeginV2(huParams, huKey, SB_DES_ECB, SB_DES_IV_SIZE, iv, &huContext, huGlobalContext);
    LOGD << "hu_DESBeginV2 return code = " << TO_HEXSTR(rc);
}

void CipherService::destroyCipher() {
    if (&huContext != NULL) {
        int rc = hu_DESEnd(&huContext, huGlobalContext);
        LOGD << "hu_DESEnd return code = " << TO_HEXSTR(rc);
        huContext = NULL;
    }
}

QString CipherService::encryptTDES(QString msg) {
    size_t pad = SB_DES_BLOCK_SIZE - (msg.length() % SB_DES_BLOCK_SIZE);

    for (uint i = 0; i < pad; i += 1) {
        msg.append(static_cast<QChar>(pad));
    }

    QByteArray plainBuf(msg.toUtf8());
    char* cipherBuf = new char[plainBuf.length()];

    LOGD << "hu_DESEncryptMsg plainBuf = " << plainBuf;

    int rc = hu_DESEncrypt(huContext,
                plainBuf.length(),
                reinterpret_cast<const unsigned char*>(plainBuf.data()),
                reinterpret_cast<unsigned char*>(cipherBuf), huGlobalContext);

    QByteArray byteData((char*)cipherBuf, plainBuf.length());
    QString result(byteData.toBase64());

    LOGD << "hu_DESEncryptMsg length = " << plainBuf.length() << " code = " << TO_HEXSTR(rc) << " result = " << result;

    return result;
}

QString CipherService::decryptTDES(QString msg) {
    QByteArray cipherBuf(QByteArray::fromBase64(msg.toUtf8()));

    if (cipherBuf.size() % SB_DES_BLOCK_SIZE) {
        cipherBuf.resize((cipherBuf.size() / SB_DES_BLOCK_SIZE) * (SB_DES_BLOCK_SIZE));
    }
    LOGD << "hu_DESEncryptMsg cipherBuf = " << msg << " length = " << cipherBuf.length();

    unsigned char* plainBuf = new unsigned char[cipherBuf.length() + 1](); // +1 to last \0

    int rc = hu_DESDecrypt(huContext,
            cipherBuf.length(),
            reinterpret_cast<const unsigned char*>(cipherBuf.data()),
            reinterpret_cast<unsigned char*>(plainBuf), huGlobalContext);

    QByteArray byteData((char*)plainBuf, cipherBuf.length());
    QString result(byteData);

    if (result.length() > 0) {
        size_t pad = (size_t) result[result.length() - 1].toAscii();
        result = result.remove(result.length() - pad, pad);
    }

    LOGD << "hu_DESDecryptMsg length = " << cipherBuf.length() << " code = " << TO_HEXSTR(rc) << " result = " << result;

    return result;
}

问题

此解决方案不起作用,在故障排除期间,我发现PHP和BB10实现之间存在两个主要差异:

问题

  • 是否可以在BlackBerry10 Cascades上使用不同的密钥长度?
  • 那里使用的密码库是什么?它来自QNX吗?
  • 我看到BB10上有openssl,但它的API看起来非常有限,是否可以在BB10上使用3DES-ECB实施openssl

链接

1 个答案:

答案 0 :(得分:0)

问题是关键。 BB创建了24字节的3DES密钥,如下所示:

QByteArray resultKey = QCryptographicHash::hash(key.toUtf8().constData(), QCryptographicHash::Md5);
resultKey.append(resultKey.mid(0, 8));

它是key这是一个字符串,通过MD%创建16字节。然后它将MD5输出的前8个字节附加到它。这会创建一个24字节的密钥,即所谓的双密钥3DES,这不安全且应该使用。

对于PHP,您需要以相同的方式创建密钥。

还要注意IV和填充。如上所述,ECB模式不使用IV,我已经一次又一次地看到pan IV被提供ECB模式,=通常是因为开发人员不了解ECB模式。

你最好在PHP中使用OpenSSL,mcrypt很糟糕。

使用一些十六进制打印来验证加密前密钥和IV是否相同。