The encryptXML - decodeEncryptedXML functions from a thread a while back cause an "isValidString" assertion to fail [resolved]


#1

Hi!

I found two very handy methods in an old, long thread (http://www.juce.com/forum/topic/software-protection-and-serial-numbers):

static const String encryptXml(const XmlElement* xml, const String& rsaPrivateKey) {
        BitArray val;

        if (xml != 0) {
            const String s(xml->createDocument(String::empty, true));
            const MemoryBlock mb(s.toUTF8(), s.length());

            val.loadFromMemoryBlock(mb);
        }

        RSAKey key(rsaPrivateKey);
        key.applyToValue(val);

        return val.toString(16);
    }

    static XmlElement* decodeEncryptedXml(const String& hexData, const String& rsaPublicKey) {
        if (hexData.isEmpty())
            return 0;

        BitArray val;
        val.parseString(hexData, 16);

        RSAKey key(rsaPublicKey);
        key.applyToValue(val);

        const MemoryBlock mb(val.toMemoryBlock());
        XmlDocument doc(mb.toString());

        XmlElement* const xml = doc.getDocumentElement();

#ifdef JUCE_DEBUG
        if (xml != 0) {
            DBG(xml->createDocument(String::empty, true));
        }
#endif

        return xml;
    }

Trouble is, while writing seems to work fine, reading causes the following assertion to fail in juce::String::fromUTF8:

   jassert (CharPointer_UTF8::isValidString (buffer, bufferSizeBytes));

An example String created by the encoder that triggers the following assertion:

2c5b39551cd283122ab1fb6aff1d7228681a2271550f2fe108f2a1918c4b6bb193ea546f433ea4d1193533dc596d6f14865ba7ec22305f551460816628506e0f6086eee12753272b2671f60c62434e33bbc00e985b97848644d610e253ab64ec9071d10efc6fd28d2cdf5b9

...In case it means anything to you :)

Any ideas why?

These functions are very handy, it'd be nice to have them around and working but I can't seem to figure out what's wrong myself!

Thanks!

 

 


#2

Scratch that, my fault, I had a corrupted private key :/

To debug this I also ended up making two functions like the above, but skipping the intermediate String stage, in case they're of any use, here they are...



static const juce::BitArray* encryptXml(const XmlElement* xml, const String& rsaPrivateKey) {
        juce::BitArray* val = new juce::BitArray();

        if (xml != 0) {
            juce::MemoryBlock destData;
            AudioProcessor::copyXmlToBinary(*xml, destData);
            val->loadFromMemoryBlock(destData);
        }

        RSAKey key(rsaPrivateKey);
        key.applyToValue(*val);

        return val;
    }

    static XmlElement* decodeEncryptedXml(BitArray& val, const String& rsaPublicKey) {
        RSAKey key(rsaPublicKey);
        key.applyToValue(val);

        const juce::MemoryBlock mb(val.toMemoryBlock());
        
        XmlElement* xml = AudioProcessor::getXmlFromBinary(mb.getData(), mb.getSize());

#ifdef JUCE_DEBUG
        if (xml != 0) {
            DBG(xml->createDocument(String::empty, true));
        }
#endif

        return xml;
    }