How to generate base64 digest string in Appian.

Certified Senior Developer

Hello All,

Below is the code snippet from Ruby.

Digest::SHA256.base64digest('')

I need to generate the same in Appian and pass it to the integration header parameter, please let me know if anyone has done this before.

Thank You,

Sneha.

  Discussion posts and replies are publicly visible

Parents
  • 0
    Certified Lead Developer

    Can you clarify on what you mean exactly by "base64 digest string"?  What is your input and what is your desired output?  If, for example, it just requires translation of a string to Base64, this can be done OOtB.

  • 0
    Certified Senior Developer
    in reply to Mike Schmitt

    Hello Mike,

    Thank You for the response.

    I need to get the equivalent hash value of the given string. First, need to get the SHA256 hash of the given string and convert the value to base64.

    I've done using Java code and exposed it as an Appian function.

  • 0
    Certified Senior Developer
    in reply to Mike Schmitt

    Sorry Mike, Missed this one. Thank you soo much. This works.

  • 0
    Certified Lead Developer
    in reply to Mani001

    great, thanks for confirming Slight smile
    (BTW if you want to "verify" my old answer(s) here that'd be great here too - i notice nobody else ever did, lol)

  • 0
    Certified Senior Developer
    in reply to Mike Schmitt

    Yes, I already tried verifying the answer but could not be able to do it. The reason may be because the owner of the conversation is different.

  • 0
    Certified Lead Developer
    in reply to Mani001

    Just out of curiosity, does that change if you click this first?

  • 0
    Certified Senior Developer
    in reply to Mike Schmitt

    yes, done Verified

  • Hello Mike,

    I tried your code & it isn't decoding Euro symbol. Here is a sample from my encoded text - "U2ltaWxhYyBBZHZhbmNlIMOiIFIwMzUxMjNQ". Can you please check. Unfortunately, I can't use decodebase64string since it has a size limitation of 2000 characters.

  • Hi Mike,

    I tried your code and it is failing to decode Euro symbol. Here is the same from my encoded text "U2ltaWxhYyBBZHZhbmNlIMOiIFIwMzUxMjNQ". Unfortunately, I can't use decodebase64string() as it has size limitation to 2000 characters.

  • 0
    Certified Lead Developer
    in reply to lalithap4822
    failing to decode Euro symbol

    Are you talking about the "â" character?  Because that's what it looks like your example string contains.  I'm unclear but for some reason my base64 back-parser is interpreting it as 2 characters instead of 1, which I'll look into - it could be an error in my parser, or some weird exception involving the convergence of character sets or something, i'm not terribly sure yet.

  • +1
    Certified Lead Developer
    in reply to lalithap4822

    After some further research, I found that extended characters (anything past char(127)) are handled specially in standard UTF-8 base64 encoding.  I did a little tampering with my existing rules and came up with the following updates today:

    Encoder:

    /* encode */
    a!localVariables(
      local!text: ri!text,
    
      local!charset: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
      local!codeArray: code(local!text),
      local!binArray: a!forEach(
        local!codeArray,
        if(
          fv!item > 127,
          if(
            fv!item > 2047,
            if(
              fv!item > 65535,
              dec2bin(fv!item, 21),
              dec2bin(fv!item, 16)
            ),
            dec2bin(fv!item, 11)
          ),
          dec2bin(fv!item, 8)
        )
      ),
      
      local!preProcessBinArray: a!forEach(
        /* encoding UTF-8 self-synchronizing (grumble) ref: https://en.wikipedia.org/wiki/UTF-8#Description */
        items: local!binArray,
        expression: a!match(
          value: len(fv!item), default: fv!item,
          
          equals: 8,
          then: fv!item,
          
          equals: 11,
          then: {
            concat( "110", left(fv!item, 5) ),
            concat( "10", right(fv!item, 6) )
          },
          
          equals: 16,
          then: {
            concat( "1110", left(fv!item, 4) ),
            concat( "10", mid(fv!item, 5, 6) ),
            concat( "10", right(fv!item, 6) )
          },
          
          equals: 21,
          then: {
            concat( "11110", left(fv!item, 3) ),
            concat( "10", mid(fv!item, 4, 6) ),
            concat( "10", mid(fv!item, 10, 6) ),
            concat( "10", right(fv!item, 6) )
          }
        )
      ),
      
      local!bins: concat(local!preProcessBinArray),
      
      local!groupedBins: split(concat(
        a!forEach(
          items: code(local!bins), 
          expression: char(fv!item) & if(and(mod(fv!index, 6) = 0, not(fv!isLast)), "-=-=-", "")
        )
      ), "-=-=-" ),
      local!lastBin: index(local!groupedBins, length(local!groupedBins)),
      local!padding: a!match(
        value: len(local!lastBin),
        equals: 2, then: "==",
        equals: 4, then: "=",
        equals: 6, then: "",
        default: "error condition"
      ),
      local!bindexes: a!forEach(
        items: local!groupedBins,
        expression: if(
          fv!isLast,
          bin2dec(substitute(padright(fv!item, 6), " ", "0")),
          bin2dec(fv!item)
        )
      ) + 1,
    
      local!assembledOutput: concat(a!forEach(items: local!bindexes, expression: charat(local!charset, fv!item))) & local!padding,
    
      local!assembledOutput
    )

    Decoder:

    /* decode */
    a!localVariables(
      local!base64text: ri!base64text,
    
      local!charset: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
    
      local!charCodes: code(local!base64text),
      /*local!paddingCount: count(wherecontains(code("="), local!charCodes)),*/
      local!unpaddedChars: a!flatten(a!forEach(
        items: local!charCodes,
        expression: if(fv!item = code("="), {}, find(char(fv!item), local!charset)-1)
      )),
      local!rawBins: dec2bin(tointeger(local!unpaddedChars), 6),
    
      local!decodedBins: split(
        concat(
          a!forEach(
            items: code(concat(local!rawBins)),
            expression: if(
              mod(fv!index, 8) = 0,
              char(fv!item) & "-=-=-",
              char(fv!item)
            )
          )
        ),
        "-=-=-"
      ),
    
      
      local!intermediaryDecodedBinList: a!flatten(a!forEach(
        /* update to handle UTF-8 self-synchronizing for extended character-set items. ref: https://en.wikipedia.org/wiki/UTF-8#Description */
        items: local!decodedBins,
        expression: if(
          or(fv!item = "0000", fv!item = "00"),
          {},
          
          a!match(
            value: fv!item, default: fv!value,
    
            /* handle 2-byte items */
            whentrue: left(fv!value, 3) = "110",
            then: concat(right(fv!item, 5), right(local!decodedBins[fv!index+1], 6)),
            whenTrue: or(  /* manually check and skip re-using subsequent ones on following iterations (ugh) */
              and(fv!index >= 2, left(local!decodedBins[fv!index-1], 3) = "110"),
            ),
            then: {},
    
            /* handle 3-byte items */
            whentrue: left(fv!value, 4) = "1110",
            then: concat(right(fv!item, 4), right(local!decodedBins[fv!index+1], 6), right(local!decodedBins[fv!index+2], 6)),
            whenTrue: or(  /* manually check and skip re-using subsequent ones on following iterations (ugh) */
              and(fv!index >= 2, left(local!decodedBins[fv!index-1], 4) = "1110"),
              and(fv!index >= 3, left(local!decodedBins[fv!index-2], 4) = "1110")
            ),
            then: {},
    
            /* handle 4-byte items */
            whentrue: left(fv!value, 5) = "11110",
            then: concat(right(fv!item, 3), right(local!decodedBins[fv!index+1], 6), right(local!decodedBins[fv!index+2], 6), right(local!decodedBins[fv!index+3], 6)),
            whenTrue: or(  /* manually check and skip re-using subsequent ones on following iterations (ugh) */
              and(fv!index >= 2, left(local!decodedBins[fv!index-1], 5) = "11110"),
              and(fv!index >= 3, left(local!decodedBins[fv!index-2], 5) = "11110"),
              and(fv!index >= 4, left(local!decodedBins[fv!index-3], 5) = "11110")
            ),
            then: {}
            
          )
        )
      )),
      
      concat(
        a!forEach(
          local!intermediaryDecodedBinList,
          char(bin2dec(fv!item))
        )
      )
    )

    These work with text containing the euro symbol and other extended character set items to an extent.  Warning that I have *not* tested them very thoroughly for corner cases (like items that exist at character set boundaries) yet, but the results so far match results given by public online base64 encoder tools.

Reply Children
No Data