1*37da2899SCharles.Forsythimplement PKCS; 2*37da2899SCharles.Forsyth 3*37da2899SCharles.Forsythinclude "sys.m"; 4*37da2899SCharles.Forsyth sys : Sys; 5*37da2899SCharles.Forsyth 6*37da2899SCharles.Forsythinclude "keyring.m"; 7*37da2899SCharles.Forsyth keyring : Keyring; 8*37da2899SCharles.Forsyth IPint : import keyring; 9*37da2899SCharles.Forsyth DESstate : import keyring; 10*37da2899SCharles.Forsyth 11*37da2899SCharles.Forsythinclude "security.m"; 12*37da2899SCharles.Forsyth random : Random; 13*37da2899SCharles.Forsyth 14*37da2899SCharles.Forsythinclude "asn1.m"; 15*37da2899SCharles.Forsyth asn1 : ASN1; 16*37da2899SCharles.Forsyth Elem, Oid : import asn1; 17*37da2899SCharles.Forsyth 18*37da2899SCharles.Forsythinclude "pkcs.m"; 19*37da2899SCharles.Forsyth 20*37da2899SCharles.Forsyth# pkcs object identifiers 21*37da2899SCharles.Forsyth 22*37da2899SCharles.ForsythobjIdTab = array [] of { 23*37da2899SCharles.Forsyth id_pkcs => Oid(array [] of {1,2,840,113549,1}), 24*37da2899SCharles.Forsyth id_pkcs_1 => Oid(array [] of {1,2,840,113549,1,1}), 25*37da2899SCharles.Forsyth id_pkcs_rsaEncryption => Oid(array [] of {1,2,840,113549,1,1,1}), 26*37da2899SCharles.Forsyth id_pkcs_md2WithRSAEncryption => Oid(array [] of {1,2,840,113549,1,1,2}), 27*37da2899SCharles.Forsyth id_pkcs_md4WithRSAEncryption => Oid(array [] of {1,2,840,113549,1,1,3}), 28*37da2899SCharles.Forsyth id_pkcs_md5WithRSAEncryption => Oid(array [] of {1,2,840,113549,1,1,4}), 29*37da2899SCharles.Forsyth 30*37da2899SCharles.Forsyth id_pkcs_3 => Oid(array [] of {1,2,840,113549,1,3}), 31*37da2899SCharles.Forsyth id_pkcs_dhKeyAgreement => Oid(array [] of {1,2,840,113549,1,3,1}), 32*37da2899SCharles.Forsyth 33*37da2899SCharles.Forsyth id_pkcs_5 => Oid(array [] of {1,2,840,113549,1,5}), 34*37da2899SCharles.Forsyth id_pkcs_pbeWithMD2AndDESCBC => Oid(array [] of {1,2,840,113549,1,5,1}), 35*37da2899SCharles.Forsyth id_pkcs_pbeWithMD5AndDESCBC => Oid(array [] of {1,2,840,113549,1,5,3}), 36*37da2899SCharles.Forsyth 37*37da2899SCharles.Forsyth id_pkcs_7 => Oid(array [] of {1,2,840,113549,1,7}), 38*37da2899SCharles.Forsyth id_pkcs_data => Oid(array [] of {1,2,840,113549,1,7,1}), 39*37da2899SCharles.Forsyth id_pkcs_singnedData => Oid(array [] of {1,2,840,113549,1,7,2}), 40*37da2899SCharles.Forsyth id_pkcs_envelopedData => Oid(array [] of {1,2,840,113549,1,7,3}), 41*37da2899SCharles.Forsyth id_pkcs_signedAndEnvelopedData => 42*37da2899SCharles.Forsyth Oid(array [] of {1,2,840,113549,1,7,4}), 43*37da2899SCharles.Forsyth id_pkcs_digestData => Oid(array [] of {1,2,840,113549,1,7,5}), 44*37da2899SCharles.Forsyth id_pkcs_encryptedData => Oid(array [] of {1,2,840,113549,1,7,6}), 45*37da2899SCharles.Forsyth 46*37da2899SCharles.Forsyth id_pkcs_9 => Oid(array [] of {1,2,840,113549,1,9}), 47*37da2899SCharles.Forsyth id_pkcs_emailAddress => Oid(array [] of {1,2,840,113549,1,9,1}), 48*37da2899SCharles.Forsyth id_pkcs_unstructuredName => Oid(array [] of {1,2,840,113549,1,9,2}), 49*37da2899SCharles.Forsyth id_pkcs_contentType => Oid(array [] of {1,2,840,113549,1,9,3}), 50*37da2899SCharles.Forsyth id_pkcs_messageDigest => Oid(array [] of {1,2,840,113549,1,9,4}), 51*37da2899SCharles.Forsyth id_pkcs_signingTime => Oid(array [] of {1,2,840,113549,1,9,5}), 52*37da2899SCharles.Forsyth id_pkcs_countersignature => Oid(array [] of {1,2,840,113549,1,9,6}), 53*37da2899SCharles.Forsyth id_pkcs_challengePassword => Oid(array [] of {1,2,840,113549,1,9,7}), 54*37da2899SCharles.Forsyth id_pkcs_unstructuredAddress => Oid(array [] of {1,2,840,113549,1,9,8}), 55*37da2899SCharles.Forsyth id_pkcs_extCertAttrs => Oid(array [] of {1,2,840,113549,1,9,9}), 56*37da2899SCharles.Forsyth id_algorithm_shaWithDSS => Oid(array [] of {1,3,14,3,2,13}) 57*37da2899SCharles.Forsyth}; 58*37da2899SCharles.Forsyth 59*37da2899SCharles.Forsyth# [public] 60*37da2899SCharles.Forsyth# initialize PKCS module 61*37da2899SCharles.Forsyth 62*37da2899SCharles.Forsythinit(): string 63*37da2899SCharles.Forsyth{ 64*37da2899SCharles.Forsyth sys = load Sys Sys->PATH; 65*37da2899SCharles.Forsyth if(sys == nil) 66*37da2899SCharles.Forsyth return "load sys module failed"; 67*37da2899SCharles.Forsyth 68*37da2899SCharles.Forsyth keyring = load Keyring Keyring->PATH; 69*37da2899SCharles.Forsyth if(keyring == nil) 70*37da2899SCharles.Forsyth return "load keyring module failed"; 71*37da2899SCharles.Forsyth 72*37da2899SCharles.Forsyth random = load Random Random->PATH; 73*37da2899SCharles.Forsyth if(random == nil) 74*37da2899SCharles.Forsyth return "load random module failed"; 75*37da2899SCharles.Forsyth 76*37da2899SCharles.Forsyth asn1 = load ASN1 ASN1->PATH; 77*37da2899SCharles.Forsyth if(asn1 == nil) 78*37da2899SCharles.Forsyth return "load asn1 module failed"; 79*37da2899SCharles.Forsyth asn1->init(); 80*37da2899SCharles.Forsyth 81*37da2899SCharles.Forsyth return ""; 82*37da2899SCharles.Forsyth} 83*37da2899SCharles.Forsyth 84*37da2899SCharles.Forsyth# [public] 85*37da2899SCharles.Forsyth# Encrypt data according to PKCS#1, with given blocktype, using given key. 86*37da2899SCharles.Forsyth 87*37da2899SCharles.Forsythrsa_encrypt(data: array of byte, key: ref RSAKey, blocktype: int) 88*37da2899SCharles.Forsyth : (string, array of byte) 89*37da2899SCharles.Forsyth{ 90*37da2899SCharles.Forsyth if(key == nil) 91*37da2899SCharles.Forsyth return ("null pkcs#1 key", nil); 92*37da2899SCharles.Forsyth k := key.modlen; 93*37da2899SCharles.Forsyth dlen := len data; 94*37da2899SCharles.Forsyth if(k < 12 || dlen > k-11) 95*37da2899SCharles.Forsyth return ("bad parameters for pkcs#1", nil); 96*37da2899SCharles.Forsyth padlen := k-3-dlen; 97*37da2899SCharles.Forsyth pad := random->randombuf(Random->NotQuiteRandom, padlen); 98*37da2899SCharles.Forsyth for(i:=0; i < padlen; i++) { 99*37da2899SCharles.Forsyth if(blocktype == 0) 100*37da2899SCharles.Forsyth pad[i] = byte 0; 101*37da2899SCharles.Forsyth else if(blocktype == 1) 102*37da2899SCharles.Forsyth pad[i] = byte 16rff; 103*37da2899SCharles.Forsyth else if(pad[i] == byte 0) 104*37da2899SCharles.Forsyth pad[i] = byte 1; 105*37da2899SCharles.Forsyth } 106*37da2899SCharles.Forsyth eb := array[k] of byte; 107*37da2899SCharles.Forsyth eb[0] = byte 0; 108*37da2899SCharles.Forsyth eb[1] = byte blocktype; 109*37da2899SCharles.Forsyth eb[2:] = pad[0:]; 110*37da2899SCharles.Forsyth eb[padlen+2] = byte 0; 111*37da2899SCharles.Forsyth eb[padlen+3:] = data[0:]; 112*37da2899SCharles.Forsyth return ("", rsacomp(eb, key)); 113*37da2899SCharles.Forsyth} 114*37da2899SCharles.Forsyth 115*37da2899SCharles.Forsyth# [public] 116*37da2899SCharles.Forsyth# Decrypt data according to PKCS#1, with given key. 117*37da2899SCharles.Forsyth# If public is true, expect a block type of 0 or 1, else 2. 118*37da2899SCharles.Forsyth 119*37da2899SCharles.Forsythrsa_decrypt(data: array of byte, key: ref RSAKey, public: int) 120*37da2899SCharles.Forsyth : (string, array of byte) 121*37da2899SCharles.Forsyth{ 122*37da2899SCharles.Forsyth eb := rsacomp(data, key); 123*37da2899SCharles.Forsyth k := key.modlen; 124*37da2899SCharles.Forsyth if(len eb == k) { 125*37da2899SCharles.Forsyth bt := int eb[1]; 126*37da2899SCharles.Forsyth if(int eb[0] == 0 && ((public && (bt == 0 || bt == 1)) || (!public && bt == 2))) { 127*37da2899SCharles.Forsyth for(i := 2; i < k; i++) 128*37da2899SCharles.Forsyth if(eb[i] == byte 0) 129*37da2899SCharles.Forsyth break; 130*37da2899SCharles.Forsyth if(i < k-1) { 131*37da2899SCharles.Forsyth ans := array[k-(i+1)] of byte; 132*37da2899SCharles.Forsyth ans[0:] = eb[i+1:]; 133*37da2899SCharles.Forsyth return ("", ans); 134*37da2899SCharles.Forsyth } 135*37da2899SCharles.Forsyth } 136*37da2899SCharles.Forsyth } 137*37da2899SCharles.Forsyth return ("pkcs1 decryption error", nil); 138*37da2899SCharles.Forsyth} 139*37da2899SCharles.Forsyth 140*37da2899SCharles.Forsyth# [private] 141*37da2899SCharles.Forsyth# Do RSA computation on block according to key, and pad 142*37da2899SCharles.Forsyth# result on left with zeros to make it key.modlen long. 143*37da2899SCharles.Forsyth 144*37da2899SCharles.Forsythrsacomp(block: array of byte, key: ref RSAKey): array of byte 145*37da2899SCharles.Forsyth{ 146*37da2899SCharles.Forsyth x := keyring->IPint.bebytestoip(block); 147*37da2899SCharles.Forsyth y := x.expmod(key.exponent, key.modulus); 148*37da2899SCharles.Forsyth ybytes := y.iptobebytes(); 149*37da2899SCharles.Forsyth k := key.modlen; 150*37da2899SCharles.Forsyth ylen := len ybytes; 151*37da2899SCharles.Forsyth if(ylen < k) { 152*37da2899SCharles.Forsyth a := array[k] of { * => byte 0}; 153*37da2899SCharles.Forsyth a[k-ylen:] = ybytes[0:]; 154*37da2899SCharles.Forsyth ybytes = a; 155*37da2899SCharles.Forsyth } 156*37da2899SCharles.Forsyth else if(ylen > k) { 157*37da2899SCharles.Forsyth # assume it has leading zeros (mod should make it so) 158*37da2899SCharles.Forsyth a := array[k] of byte; 159*37da2899SCharles.Forsyth a[0:] = ybytes[ylen-k:]; 160*37da2899SCharles.Forsyth ybytes = a; 161*37da2899SCharles.Forsyth } 162*37da2899SCharles.Forsyth return ybytes; 163*37da2899SCharles.Forsyth} 164*37da2899SCharles.Forsyth 165*37da2899SCharles.Forsyth# [public] 166*37da2899SCharles.Forsyth 167*37da2899SCharles.Forsythrsa_sign(data: array of byte, sk: ref RSAKey, algid: int): (string, array of byte) 168*37da2899SCharles.Forsyth{ 169*37da2899SCharles.Forsyth # digesting and add proper padding to it 170*37da2899SCharles.Forsyth ph := padhash(data, algid); 171*37da2899SCharles.Forsyth 172*37da2899SCharles.Forsyth return rsa_encrypt(ph, sk, 0); # blocktype <- padding with zero 173*37da2899SCharles.Forsyth} 174*37da2899SCharles.Forsyth 175*37da2899SCharles.Forsyth# [public] 176*37da2899SCharles.Forsyth 177*37da2899SCharles.Forsythrsa_verify(data, signature: array of byte, pk: ref RSAKey, algid: int): int 178*37da2899SCharles.Forsyth{ 179*37da2899SCharles.Forsyth # digesting and add proper padding to it 180*37da2899SCharles.Forsyth ph := padhash(data, algid); 181*37da2899SCharles.Forsyth 182*37da2899SCharles.Forsyth (err, orig) := rsa_decrypt(signature, pk, 0); # blocktype ? 183*37da2899SCharles.Forsyth if(err != "" || !byte_cmp(orig, ph)) 184*37da2899SCharles.Forsyth return 0; 185*37da2899SCharles.Forsyth 186*37da2899SCharles.Forsyth return 1; 187*37da2899SCharles.Forsyth} 188*37da2899SCharles.Forsyth 189*37da2899SCharles.Forsyth# [private] 190*37da2899SCharles.Forsyth# padding block A 191*37da2899SCharles.ForsythPA := array [] of { 192*37da2899SCharles.Forsyth byte 16r30, byte 16r20, byte 16r30, byte 16r0c, 193*37da2899SCharles.Forsyth byte 16r06, byte 16r08, byte 16r2a, byte 16r86, 194*37da2899SCharles.Forsyth byte 16r48, byte 16r86, byte 16rf7, byte 16r0d, 195*37da2899SCharles.Forsyth byte 16r02 196*37da2899SCharles.Forsyth}; 197*37da2899SCharles.Forsyth 198*37da2899SCharles.Forsyth# [private] 199*37da2899SCharles.Forsyth# padding block B 200*37da2899SCharles.ForsythPB := array [] of {byte 16r05, byte 16r00, byte 16r04, byte 16r10}; 201*37da2899SCharles.Forsyth 202*37da2899SCharles.Forsyth# [private] 203*37da2899SCharles.Forsyth# require either md5 or md2 of 16 bytes digest 204*37da2899SCharles.Forsyth# length of padded digest = 13 + 1 + 4 + 16 205*37da2899SCharles.Forsyth 206*37da2899SCharles.Forsythpadhash(data: array of byte, algid: int): array of byte 207*37da2899SCharles.Forsyth{ 208*37da2899SCharles.Forsyth padded := array [34] of byte; 209*37da2899SCharles.Forsyth case algid { 210*37da2899SCharles.Forsyth MD2_WithRSAEncryption => 211*37da2899SCharles.Forsyth padded[13] = byte 2; 212*37da2899SCharles.Forsyth # TODO: implement md2 in keyring module 213*37da2899SCharles.Forsyth # keyring->md2(data, len data, padded[18:], nil); 214*37da2899SCharles.Forsyth 215*37da2899SCharles.Forsyth MD5_WithRSAEncryption => 216*37da2899SCharles.Forsyth padded[13] = byte 5; 217*37da2899SCharles.Forsyth keyring->md5(data, len data, padded[18:], nil); 218*37da2899SCharles.Forsyth * => 219*37da2899SCharles.Forsyth return nil; 220*37da2899SCharles.Forsyth } 221*37da2899SCharles.Forsyth padded[0:] = PA; 222*37da2899SCharles.Forsyth padded[14:] = PB; 223*37da2899SCharles.Forsyth 224*37da2899SCharles.Forsyth return padded; 225*37da2899SCharles.Forsyth} 226*37da2899SCharles.Forsyth 227*37da2899SCharles.Forsyth# [private] 228*37da2899SCharles.Forsyth# compare byte to byte of two array of byte 229*37da2899SCharles.Forsyth 230*37da2899SCharles.Forsythbyte_cmp(a, b: array of byte): int 231*37da2899SCharles.Forsyth{ 232*37da2899SCharles.Forsyth if(len a != len b) 233*37da2899SCharles.Forsyth return 0; 234*37da2899SCharles.Forsyth 235*37da2899SCharles.Forsyth for(i := 0; i < len a; i++) { 236*37da2899SCharles.Forsyth if(a[i] != b[i]) 237*37da2899SCharles.Forsyth return 0; 238*37da2899SCharles.Forsyth } 239*37da2899SCharles.Forsyth 240*37da2899SCharles.Forsyth return 1; 241*37da2899SCharles.Forsyth} 242*37da2899SCharles.Forsyth 243*37da2899SCharles.Forsyth# [public] 244*37da2899SCharles.Forsyth 245*37da2899SCharles.ForsythRSAKey.bits(key: self ref RSAKey): int 246*37da2899SCharles.Forsyth{ 247*37da2899SCharles.Forsyth return key.modulus.bits(); 248*37da2899SCharles.Forsyth} 249*37da2899SCharles.Forsyth 250*37da2899SCharles.Forsyth# [public] 251*37da2899SCharles.Forsyth# Decode an RSAPublicKey ASN1 type, defined as: 252*37da2899SCharles.Forsyth# 253*37da2899SCharles.Forsyth# RSAPublickKey :: SEQUENCE { 254*37da2899SCharles.Forsyth# modulus INTEGER, 255*37da2899SCharles.Forsyth# publicExponent INTEGER 256*37da2899SCharles.Forsyth# } 257*37da2899SCharles.Forsyth 258*37da2899SCharles.Forsythdecode_rsapubkey(a: array of byte): (string, ref RSAKey) 259*37da2899SCharles.Forsyth{ 260*37da2899SCharles.Forsythparse: 261*37da2899SCharles.Forsyth for(;;) { 262*37da2899SCharles.Forsyth (err, e) := asn1->decode(a); 263*37da2899SCharles.Forsyth if(err != "") 264*37da2899SCharles.Forsyth break parse; 265*37da2899SCharles.Forsyth (ok, el) := e.is_seq(); 266*37da2899SCharles.Forsyth if(!ok || len el != 2) 267*37da2899SCharles.Forsyth break parse; 268*37da2899SCharles.Forsyth modbytes, expbytes: array of byte; 269*37da2899SCharles.Forsyth (ok, modbytes) = (hd el).is_bigint(); 270*37da2899SCharles.Forsyth if(!ok) 271*37da2899SCharles.Forsyth break parse; 272*37da2899SCharles.Forsyth modulus := IPint.bebytestoip(modbytes); 273*37da2899SCharles.Forsyth # get modlen this way, because sometimes it 274*37da2899SCharles.Forsyth # comes with leading zeros that are to be ignored! 275*37da2899SCharles.Forsyth mbytes := modulus.iptobebytes(); 276*37da2899SCharles.Forsyth modlen := len mbytes; 277*37da2899SCharles.Forsyth (ok, expbytes) = (hd tl el).is_bigint(); 278*37da2899SCharles.Forsyth if(!ok) 279*37da2899SCharles.Forsyth break parse; 280*37da2899SCharles.Forsyth exponent := keyring->IPint.bebytestoip(expbytes); 281*37da2899SCharles.Forsyth return ("", ref RSAKey(modulus, modlen, exponent)); 282*37da2899SCharles.Forsyth } 283*37da2899SCharles.Forsyth return ("rsa public key: syntax error", nil); 284*37da2899SCharles.Forsyth} 285*37da2899SCharles.Forsyth 286*37da2899SCharles.Forsyth 287*37da2899SCharles.Forsyth# [public] 288*37da2899SCharles.Forsyth# generate a pair of DSS public and private keys 289*37da2899SCharles.Forsyth 290*37da2899SCharles.ForsythgenerateDSSKeyPair(strength: int): (ref DSSPublicKey, ref DSSPrivateKey) 291*37da2899SCharles.Forsyth{ 292*37da2899SCharles.Forsyth # TODO: need add getRandBetween in IPint 293*37da2899SCharles.Forsyth return (nil, nil); 294*37da2899SCharles.Forsyth} 295*37da2899SCharles.Forsyth 296*37da2899SCharles.Forsyth# [public] 297*37da2899SCharles.Forsyth 298*37da2899SCharles.Forsythdss_sign(a: array of byte, sk: ref DSSPrivateKey): (string, array of byte) 299*37da2899SCharles.Forsyth{ 300*37da2899SCharles.Forsyth #signature, digest: array of byte; 301*37da2899SCharles.Forsyth 302*37da2899SCharles.Forsyth #case hash { 303*37da2899SCharles.Forsyth #Keyring->MD4 => 304*37da2899SCharles.Forsyth # digest = array [Keyring->MD4dlen] of byte; 305*37da2899SCharles.Forsyth # keyring->md4(a, len a, digest, nil); 306*37da2899SCharles.Forsyth #Keyring->MD5 => 307*37da2899SCharles.Forsyth # digest = array [Keyring->MD5dlen] of byte; 308*37da2899SCharles.Forsyth # keyring->md5(a, len a, digest, nil); 309*37da2899SCharles.Forsyth #Keyring->SHA => 310*37da2899SCharles.Forsyth # digest = array [Keyring->SHA1dlen] of byte; 311*37da2899SCharles.Forsyth # keyring->sha1(a, len a, digest, nil); 312*37da2899SCharles.Forsyth #* => 313*37da2899SCharles.Forsyth # return ("unknown hash algorithm", nil); 314*37da2899SCharles.Forsyth #} 315*37da2899SCharles.Forsyth 316*37da2899SCharles.Forsyth # TODO: add gcd or getRandBetween in Keyring->IPint 317*37da2899SCharles.Forsyth return ("unsupported error", nil); 318*37da2899SCharles.Forsyth} 319*37da2899SCharles.Forsyth 320*37da2899SCharles.Forsyth# [public] 321*37da2899SCharles.Forsyth 322*37da2899SCharles.Forsythdss_verify(a, signa: array of byte, pk: ref DSSPublicKey): int 323*37da2899SCharles.Forsyth{ 324*37da2899SCharles.Forsyth unsigned: array of byte; 325*37da2899SCharles.Forsyth 326*37da2899SCharles.Forsyth #case hash { 327*37da2899SCharles.Forsyth #Keyring->MD4 => 328*37da2899SCharles.Forsyth # digest = array [Keyring->MD4dlen] of byte; 329*37da2899SCharles.Forsyth # keyring->md4(a, len a, digest, nil); 330*37da2899SCharles.Forsyth #Keyring->MD5 => 331*37da2899SCharles.Forsyth # digest = array [Keyring->MD5dlen] of byte; 332*37da2899SCharles.Forsyth # keyring->md5(a, len a, digest, nil); 333*37da2899SCharles.Forsyth #Keyring->SHA => 334*37da2899SCharles.Forsyth # digest = array [Keyring->SHA1dlen] of byte; 335*37da2899SCharles.Forsyth # keyring->sha1(a, len a, digest, nil); 336*37da2899SCharles.Forsyth #* => 337*37da2899SCharles.Forsyth # return 0; 338*37da2899SCharles.Forsyth #} 339*37da2899SCharles.Forsyth 340*37da2899SCharles.Forsyth # get unsigned from signa and compare it with digest 341*37da2899SCharles.Forsyth 342*37da2899SCharles.Forsyth if(byte_cmp(unsigned, a)) 343*37da2899SCharles.Forsyth return 1; 344*37da2899SCharles.Forsyth 345*37da2899SCharles.Forsyth return 0; 346*37da2899SCharles.Forsyth} 347*37da2899SCharles.Forsyth 348*37da2899SCharles.Forsyth# [public] 349*37da2899SCharles.Forsythdecode_dsspubkey(a: array of byte): (string, ref DSSPublicKey) 350*37da2899SCharles.Forsyth{ 351*37da2899SCharles.Forsyth return ("unsupported error", nil); 352*37da2899SCharles.Forsyth} 353*37da2899SCharles.Forsyth 354*37da2899SCharles.Forsyth 355*37da2899SCharles.Forsyth# [public] 356*37da2899SCharles.Forsyth# generate DH parameters with prime length at least (default) 512 bits 357*37da2899SCharles.Forsyth 358*37da2899SCharles.ForsythgenerateDHParams(primelen: int): ref DHParams 359*37da2899SCharles.Forsyth{ 360*37da2899SCharles.Forsyth # prime - at least 512 bits 361*37da2899SCharles.Forsyth if(primelen < 512) # DHmodlen 362*37da2899SCharles.Forsyth primelen = 512; 363*37da2899SCharles.Forsyth 364*37da2899SCharles.Forsyth # generate prime and base (generator) integers 365*37da2899SCharles.Forsyth (p, g) := keyring->dhparams(primelen); 366*37da2899SCharles.Forsyth if(p == nil || g == nil) 367*37da2899SCharles.Forsyth return nil; 368*37da2899SCharles.Forsyth 369*37da2899SCharles.Forsyth return ref DHParams(p, g, 0); 370*37da2899SCharles.Forsyth} 371*37da2899SCharles.Forsyth 372*37da2899SCharles.Forsyth# [public] 373*37da2899SCharles.Forsyth# generate public and private key pair 374*37da2899SCharles.Forsyth# Note: use iptobytes as integer to octet string conversion 375*37da2899SCharles.Forsyth# and bytestoip as octect string to integer reversion 376*37da2899SCharles.Forsyth 377*37da2899SCharles.ForsythsetupDHAgreement(dh: ref DHParams): (ref DHPrivateKey, ref DHPublicKey) 378*37da2899SCharles.Forsyth{ 379*37da2899SCharles.Forsyth if(dh == nil || dh.prime == nil || dh.base == nil) 380*37da2899SCharles.Forsyth return (nil, nil); 381*37da2899SCharles.Forsyth 382*37da2899SCharles.Forsyth # prime length in bits 383*37da2899SCharles.Forsyth bits := dh.prime.bits(); 384*37da2899SCharles.Forsyth 385*37da2899SCharles.Forsyth # generate random private key of length between bits/4 and bits 386*37da2899SCharles.Forsyth x := IPint.random(bits/4, bits); 387*37da2899SCharles.Forsyth if(x == nil) 388*37da2899SCharles.Forsyth return (nil, nil); 389*37da2899SCharles.Forsyth dh.privateValueLength = x.bits(); 390*37da2899SCharles.Forsyth 391*37da2899SCharles.Forsyth # calculate public key 392*37da2899SCharles.Forsyth y := dh.base.expmod(x, dh.prime); 393*37da2899SCharles.Forsyth if(y == nil) 394*37da2899SCharles.Forsyth return (nil, nil); 395*37da2899SCharles.Forsyth 396*37da2899SCharles.Forsyth return (ref DHPrivateKey(dh, y, x), ref DHPublicKey(dh, x)); 397*37da2899SCharles.Forsyth} 398*37da2899SCharles.Forsyth 399*37da2899SCharles.Forsyth# [public] 400*37da2899SCharles.Forsyth# The second phase of Diffie-Hellman key agreement 401*37da2899SCharles.Forsyth 402*37da2899SCharles.ForsythcomputeDHAgreedKey(dh: ref DHParams, mysk, upk: ref IPint) 403*37da2899SCharles.Forsyth : array of byte 404*37da2899SCharles.Forsyth{ 405*37da2899SCharles.Forsyth if(mysk == nil || upk == nil) 406*37da2899SCharles.Forsyth return nil; 407*37da2899SCharles.Forsyth 408*37da2899SCharles.Forsyth # exponential - calculate agreed key (shared secret) 409*37da2899SCharles.Forsyth z := upk.expmod(mysk, dh.prime); 410*37da2899SCharles.Forsyth 411*37da2899SCharles.Forsyth # integer to octet conversion 412*37da2899SCharles.Forsyth return z.iptobebytes(); 413*37da2899SCharles.Forsyth} 414*37da2899SCharles.Forsyth 415*37da2899SCharles.Forsyth# [public] 416*37da2899SCharles.Forsyth# ASN1 encoding 417*37da2899SCharles.Forsyth 418*37da2899SCharles.Forsythdecode_dhpubkey(a: array of byte): (string, ref DHPublicKey) 419*37da2899SCharles.Forsyth{ 420*37da2899SCharles.Forsyth return ("unsupported error", nil); 421*37da2899SCharles.Forsyth} 422*37da2899SCharles.Forsyth 423*37da2899SCharles.Forsyth 424*37da2899SCharles.Forsyth# [public] 425*37da2899SCharles.Forsyth# Digest the concatenation of password and salt with count iterations of 426*37da2899SCharles.Forsyth# selected message-digest algorithm (either md2 or md5). 427*37da2899SCharles.Forsyth# The first 8 bytes of the message digest become the DES key. 428*37da2899SCharles.Forsyth# The last 8 bytes of the message digest become the initializing vector IV. 429*37da2899SCharles.Forsyth 430*37da2899SCharles.ForsythgenerateDESKey(pw: array of byte, param: ref PBEParams, alg: int) 431*37da2899SCharles.Forsyth : (ref DESstate, array of byte, array of byte) 432*37da2899SCharles.Forsyth{ 433*37da2899SCharles.Forsyth if(param.iterationCount < 1) 434*37da2899SCharles.Forsyth return (nil, nil, nil); 435*37da2899SCharles.Forsyth 436*37da2899SCharles.Forsyth # concanate password and salt 437*37da2899SCharles.Forsyth pwlen := len pw; 438*37da2899SCharles.Forsyth pslen := pwlen + len param.salt; 439*37da2899SCharles.Forsyth ps := array [pslen] of byte; 440*37da2899SCharles.Forsyth ps[0:] = pw; 441*37da2899SCharles.Forsyth ps[pwlen:] = param.salt; 442*37da2899SCharles.Forsyth key, iv: array of byte; 443*37da2899SCharles.Forsyth 444*37da2899SCharles.Forsyth # digest iterations 445*37da2899SCharles.Forsyth case alg { 446*37da2899SCharles.Forsyth PBE_MD2_DESCBC => 447*37da2899SCharles.Forsyth ds : ref Keyring->DigestState = nil; 448*37da2899SCharles.Forsyth # TODO: implement md2 in keyring module 449*37da2899SCharles.Forsyth #result := array [Keyring->MD2dlen] of byte; 450*37da2899SCharles.Forsyth #for(i := 0; i < param.iterationCount; i++) 451*37da2899SCharles.Forsyth # ds = keyring->md2(ps, pslen, nil, ds); 452*37da2899SCharles.Forsyth #keyring->md2(ps, pslen, result, ds); 453*37da2899SCharles.Forsyth #key = result[0:8]; 454*37da2899SCharles.Forsyth #iv = result[8:]; 455*37da2899SCharles.Forsyth 456*37da2899SCharles.Forsyth PBE_MD5_DESCBC => 457*37da2899SCharles.Forsyth ds: ref Keyring->DigestState = nil; 458*37da2899SCharles.Forsyth result := array [Keyring->MD5dlen] of byte; 459*37da2899SCharles.Forsyth for(i := 0; i < param.iterationCount; i++) 460*37da2899SCharles.Forsyth ds = keyring->md5(ps, pslen, nil, ds); 461*37da2899SCharles.Forsyth keyring->md5(ps, pslen, result, ds); 462*37da2899SCharles.Forsyth key = result[0:8]; 463*37da2899SCharles.Forsyth iv = result[8:]; 464*37da2899SCharles.Forsyth 465*37da2899SCharles.Forsyth * => 466*37da2899SCharles.Forsyth return (nil, nil, nil); 467*37da2899SCharles.Forsyth } 468*37da2899SCharles.Forsyth 469*37da2899SCharles.Forsyth state := keyring->dessetup(key, iv); 470*37da2899SCharles.Forsyth 471*37da2899SCharles.Forsyth return (state, key, iv); 472*37da2899SCharles.Forsyth} 473*37da2899SCharles.Forsyth 474*37da2899SCharles.Forsyth# [public] 475*37da2899SCharles.Forsyth# The message M and a padding string PS shall be formatted into 476*37da2899SCharles.Forsyth# an octet string EB 477*37da2899SCharles.Forsyth# EB = M + PS 478*37da2899SCharles.Forsyth# where 479*37da2899SCharles.Forsyth# PS = 1 if M mod 8 = 7; 480*37da2899SCharles.Forsyth# PS = 2 + 2 if M mod 8 = 6; 481*37da2899SCharles.Forsyth# ... 482*37da2899SCharles.Forsyth# PS = 8 + 8 + 8 + 8 + 8 + 8 + 8 + 8 if M mod 8 = 0; 483*37da2899SCharles.Forsyth 484*37da2899SCharles.Forsythpbe_encrypt(state: ref DESstate, m: array of byte): array of byte 485*37da2899SCharles.Forsyth{ 486*37da2899SCharles.Forsyth mlen := len m; 487*37da2899SCharles.Forsyth padvalue := mlen % 8; 488*37da2899SCharles.Forsyth pdlen := 8 - padvalue; 489*37da2899SCharles.Forsyth 490*37da2899SCharles.Forsyth eb := array [mlen + pdlen] of byte; 491*37da2899SCharles.Forsyth eb[0:] = m; 492*37da2899SCharles.Forsyth for(i := mlen; i < pdlen; i++) 493*37da2899SCharles.Forsyth eb[i] = byte padvalue; 494*37da2899SCharles.Forsyth 495*37da2899SCharles.Forsyth keyring->descbc(state, eb, len eb, Keyring->Encrypt); 496*37da2899SCharles.Forsyth 497*37da2899SCharles.Forsyth return eb; 498*37da2899SCharles.Forsyth} 499*37da2899SCharles.Forsyth 500*37da2899SCharles.Forsyth# [public] 501*37da2899SCharles.Forsyth 502*37da2899SCharles.Forsythpbe_decrypt(state: ref DESstate, eb: array of byte): array of byte 503*37da2899SCharles.Forsyth{ 504*37da2899SCharles.Forsyth eblen := len eb; 505*37da2899SCharles.Forsyth if(eblen%8 != 0) # must a multiple of 8 bytes 506*37da2899SCharles.Forsyth return nil; 507*37da2899SCharles.Forsyth 508*37da2899SCharles.Forsyth keyring->descbc(state, eb, eblen, Keyring->Decrypt); 509*37da2899SCharles.Forsyth 510*37da2899SCharles.Forsyth # remove padding 511*37da2899SCharles.Forsyth for(i := eblen -8; i < 8; i++) { 512*37da2899SCharles.Forsyth if(int eb[i] == i) { 513*37da2899SCharles.Forsyth for(j := i; j < 8; j++) 514*37da2899SCharles.Forsyth if(int eb[j] != i) 515*37da2899SCharles.Forsyth break; 516*37da2899SCharles.Forsyth if(j == 8) 517*37da2899SCharles.Forsyth break; 518*37da2899SCharles.Forsyth } 519*37da2899SCharles.Forsyth } 520*37da2899SCharles.Forsyth 521*37da2899SCharles.Forsyth return eb[0:i]; 522*37da2899SCharles.Forsyth} 523*37da2899SCharles.Forsyth 524*37da2899SCharles.Forsyth# [public] 525*37da2899SCharles.Forsyth 526*37da2899SCharles.ForsythPrivateKeyInfo.encode(p: self ref PrivateKeyInfo): (string, array of byte) 527*37da2899SCharles.Forsyth{ 528*37da2899SCharles.Forsyth 529*37da2899SCharles.Forsyth return ("unsupported error", nil); 530*37da2899SCharles.Forsyth} 531*37da2899SCharles.Forsyth 532*37da2899SCharles.Forsyth# [public] 533*37da2899SCharles.Forsyth 534*37da2899SCharles.ForsythPrivateKeyInfo.decode(a: array of byte): (string, ref PrivateKeyInfo) 535*37da2899SCharles.Forsyth{ 536*37da2899SCharles.Forsyth return ("unsupported error", nil); 537*37da2899SCharles.Forsyth} 538*37da2899SCharles.Forsyth 539*37da2899SCharles.Forsyth# [public] 540*37da2899SCharles.Forsyth 541*37da2899SCharles.ForsythEncryptedPrivateKeyInfo.encode(p: self ref EncryptedPrivateKeyInfo) 542*37da2899SCharles.Forsyth : (string, array of byte) 543*37da2899SCharles.Forsyth{ 544*37da2899SCharles.Forsyth 545*37da2899SCharles.Forsyth return ("unsupported error", nil); 546*37da2899SCharles.Forsyth} 547*37da2899SCharles.Forsyth 548*37da2899SCharles.Forsyth# [public] 549*37da2899SCharles.Forsyth 550*37da2899SCharles.ForsythEncryptedPrivateKeyInfo.decode(a: array of byte) 551*37da2899SCharles.Forsyth : (string, ref EncryptedPrivateKeyInfo) 552*37da2899SCharles.Forsyth{ 553*37da2899SCharles.Forsyth return ("unsupported error", nil); 554*37da2899SCharles.Forsyth} 555*37da2899SCharles.Forsyth 556*37da2899SCharles.Forsyth# [public] 557*37da2899SCharles.Forsyth 558*37da2899SCharles.Forsythdecode_extcertorcert(a: array of byte): (int, int, array of byte) 559*37da2899SCharles.Forsyth{ 560*37da2899SCharles.Forsyth (err, all) := asn1->decode(a); 561*37da2899SCharles.Forsyth if(err == "") { 562*37da2899SCharles.Forsyth 563*37da2899SCharles.Forsyth } 564*37da2899SCharles.Forsyth} 565*37da2899SCharles.Forsyth 566*37da2899SCharles.Forsyth# [public] 567*37da2899SCharles.Forsyth 568*37da2899SCharles.Forsythencode_extcertorcert(a: array of byte, which: int): (int, array of byte) 569*37da2899SCharles.Forsyth{ 570*37da2899SCharles.Forsyth 571*37da2899SCharles.Forsyth} 572*37da2899SCharles.Forsyth 573