Skip to content

Instantly share code, notes, and snippets.

@raimo
Forked from andrewconner/UserVoiceTokenGenerator.scala
Last active February 22, 2018 20:21
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save raimo/5572215 to your computer and use it in GitHub Desktop.
Save raimo/5572215 to your computer and use it in GitHub Desktop.
// Based on Andrew Conner's example at https://gist.github.com/andrewconner/5510961
import org.apache.commons.codec.net.URLCodec
import org.apache.commons.codec.binary.Base64
import javax.crypto.spec.SecretKeySpec
import javax.crypto.spec.IvParameterSpec
import org.apache.commons.codec.digest.DigestUtils
import java.io.InputStream
import java.io.OutputStream
import javax.crypto.Cipher
import javax.crypto.CipherOutputStream
import java.io.ByteArrayOutputStream
import java.io.ByteArrayInputStream
object UserVoiceTokenGenerator {
private final val USERVOICE_SUBDOMAIN = "<insert UserVoice subdomain>"
private final val SSO_KEY = "<insert UserVoice SSO key>"
private final val INIT_VECTOR = "OpenSSL for Ruby".getBytes()
private val hash = DigestUtils.sha(SSO_KEY + USERVOICE_SUBDOMAIN).toSeq
private val secretKeySpec = new SecretKeySpec(hash.take(16).toArray, "AES")
private val ivSpec = new IvParameterSpec(INIT_VECTOR)
private val urlCodec = new URLCodec("ASCII")
private val base64 = new Base64()
private def encrypt(in: InputStream): ByteArrayOutputStream = {
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec)
val buf = new Array[Byte](1024)
val byteStream = new ByteArrayOutputStream()
val out = new CipherOutputStream(byteStream, cipher)
try {
Iterator.continually(in.read(buf)).takeWhile(_ >= 0) foreach { numRead =>
out.write(buf, 0, numRead)
}
} catch {
case ex: Throwable =>
// integrate your application logging
ex.printStackTrace()
} finally {
out.close()
}
byteStream
}
def create(json: String): String = {
val jsonBytes = json.getBytes()
val data = INIT_VECTOR.zip(jsonBytes).take(16).map({ case (i, d) => (i ^ d).byteValue }) ++ jsonBytes.drop(INIT_VECTOR.length)
val out = encrypt(new ByteArrayInputStream(data));
new String(urlCodec.encode(base64.encode(out.toByteArray)))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment