· 6 years ago · Jun 29, 2019, 12:36 AM
1class Person private constructor(val name :String,
2 private val keyPair: KeyPair) {
3
4 val publicKey : PublicKey
5 get() = keyPair.public
6 private val privateKey : PrivateKey
7 get() = keyPair.private ?: error("Current Person implementation doesn't support functions that use the private key")
8
9 fun isValid() = fromPrivateKey(name,privateKey).publicKey == publicKey
10
11 override fun toString(): String {
12 return "Person(name=$name, finger=${fingerprint().substring(0,10)})"
13 }
14
15
16 fun sign(data :ByteArray): Signature {
17 sig.initSign(privateKey)
18 sig.update(data)
19 return Signature(sig.sign())
20 }
21
22 fun fingerprint():String = DigestUtils.sha1Hex(publicKey.encoded)
23
24 /** This needs to be below 245 bytes */
25 fun encrypt(data :ByteArray, publicKey: PublicKey): ByteArray {
26 val cipher = Cipher.getInstance("RSA")
27 cipher.init(Cipher.ENCRYPT_MODE, publicKey)
28 return cipher.doFinal(data)
29 }
30
31 /** This needs to be below 245 bytes */
32 fun encrypt(data :ByteArray, person :Person):ByteArray = encrypt(data,person.publicKey)
33
34 /** This needs to be below 245 bytes */
35 fun decrypt(encrypted: ByteArray): ByteArray {
36 val cipher = Cipher.getInstance("RSA")
37 cipher.init(Cipher.DECRYPT_MODE, privateKey)
38 return cipher.doFinal(encrypted)
39 }
40
41
42 /** This will encrypt over 245 bytes */
43 fun encryptAES(data :ByteArray,person :Person):EncryptedData = encryptAES(data,person.publicKey)
44
45 /** This will encrypt over 245 bytes */
46 fun encryptAES(data :ByteArray, publicKey : PublicKey): EncryptedData {
47 val iv = ByteArray(16) { -1 }
48 SecureRandom.getInstanceStrong().nextBytes(iv)
49
50 val keyGen = KeyGenerator.getInstance("AES")
51 keyGen.init(128)
52 val secretKey = keyGen.generateKey()
53
54
55 val ivParameterSpec = IvParameterSpec(iv)
56 val aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
57 aesCipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec)
58
59 val final = aesCipher.doFinal(data)
60 return EncryptedData(iv, encrypt(secretKey.encoded,publicKey), final)
61 //need to return encrypted secret key and the encrypted message
62 }
63
64 fun decryptAES(data : EncryptedData) :ByteArray{
65 val iv = data.iv
66 val ivParameterSpec = IvParameterSpec(iv)
67
68 val decryptedSecretKey = decrypt(data.encryptedSecretKey)
69
70 val secretKey = SecretKeySpec(decryptedSecretKey, 0, decryptedSecretKey.size, "AES")
71
72
73 val aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
74 aesCipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec)
75
76 return aesCipher.doFinal(data.encryptedData)
77 }
78
79companion object {
80 private val sig = java.security.Signature.getInstance("SHA1WithRSA")
81
82 fun verify(publicKey: PublicKey, signature: Signature, data: ByteArray): Boolean {
83 sig.initVerify(publicKey)
84 sig.update(data)
85 return sig.verify(signature.byteArray)
86 }
87
88 //buildKeyPair(DigestUtils.sha1(name)!!.contentHashCode().toLong())
89 private fun buildKeyPair(seed :Long): KeyPair {
90 val random = SecureRandom.getInstance("SHA1PRNG")
91 random.setSeed(seed)
92 val keySize = 2048
93 val keyPairGenerator = KeyPairGenerator.getInstance("RSA")
94 keyPairGenerator.initialize(keySize,random)
95 return keyPairGenerator.genKeyPair()
96 }
97
98 private fun buildKeyPair():KeyPair {
99 val keySize = 2048
100 val keyPairGenerator = KeyPairGenerator.getInstance("RSA")
101 keyPairGenerator.initialize(keySize)
102 return keyPairGenerator.genKeyPair()
103 }
104
105
106 //generators
107 fun fromKeyPair(name :String, keyPair: KeyPair):Person = Person(name, keyPair)
108 fun fromPublicKey(name :String, publicKey: PublicKey):Person = Person(name,KeyPair(publicKey,null))
109 fun fromPrivateKey(name :String, privateKey: PrivateKey):Person {
110 //attempt to find the correct public key
111 if(privateKey !is RSAPrivateCrtKey)
112 error("Private key is not a RSAPrivateCrtKey and does not contain enough data to compute the public key")
113 val spec = RSAPublicKeySpec(privateKey.modulus,privateKey.publicExponent)
114 val factory = KeyFactory.getInstance("RSA")
115 val publicKey = factory.generatePublic(spec)
116 return Person(name, KeyPair(publicKey,privateKey))
117 }
118 fun deterministicFromName(name :String) :Person = Person(name,buildKeyPair(DigestUtils.sha1(name)!!.contentHashCode().toLong()))
119 fun generateNew(name :String) :Person = Person(name, buildKeyPair())
120 }
121
122class Signature(val byteArray: ByteArray) {
123 override fun equals(other: Any?): Boolean {
124 if (this === other) return true
125 if (javaClass != other?.javaClass) return false
126
127 other as Signature
128
129 if (!byteArray.contentEquals(other.byteArray)) return false
130
131 return true
132 }
133
134 override fun hashCode(): Int {
135 return byteArray.contentHashCode()
136 }
137}
138
139class EncryptedData(val iv :ByteArray, val encryptedSecretKey :ByteArray,val encryptedData :ByteArray)