func prefix(b []byte) []byte { sha256 := sha256.New() sha256.Write(b) h := sha256.Sum(nil) sha256.Reset() sha256.Write(h) cs := sha256.Sum(nil) return cs[:4] }
func IdForKey(pk rsa.PublicKey) Id { // Write the Rsa64 representation of public key into Sha256 pk64 := []byte(rsa64.PubToBase64(&pk)) sha256 := sha256.New() for { n, err := sha256.Write(pk64) if err != nil { panic("sha256 malfunction") } if n == len(pk64) { break } pk64 = pk64[n:] } // Compute and fold the Sha256 hash h := sha256.Sum() if len(h) != 32 { panic("expecting 32 bytes") } for i := 1; i < 4; i++ { for j := 0; j < 8; j++ { h[j] ^= h[8*i+j] } } id64, err := bytes.BytesToInt64(h[0:8]) if err != nil { panic("logic") } return Id(id64) }
func main() { fmt.Println("Start...") // String from: // http://en.wikipedia.org/wiki/WebSocket s := "x3JJHMbDL1EzLkh9GBhXDw==258EAFA5-E914-47DA-95CA-C5AB0DC85B11" // sha1 stuff ... sha1 := sha1.New() sha1.Write([]byte(s)) ss := fmt.Sprintf("%x", sha1.Sum(nil)) fmt.Printf("%s\n", ss) w := "1d29ab734b0c9585240069a6e4e3e91b61da1969" fmt.Printf("%s\n", w) if ss != w { panic("Uh oh, something is not right") } // --------------------------------------------------------------------------- // The base64 encoding part of that post is left as an exercise for now. // From the article the base64 result should be: // HSmrc0sMlYUkAGmm5OPpG2HaGWk= // *not tested* // --------------------------------------------------------------------------- // sha256 stuff ... sha256 := sha256.New() sha256.Write([]byte(s)) ss = fmt.Sprintf("%x", sha256.Sum(nil)) fmt.Printf("%s\n", ss) fmt.Println("End...") }
func (s *SimpleStreams) downloadFile(path string, hash string, target string, progress func(int)) error { download := func(url string, hash string, target string) error { out, err := os.Create(target) if err != nil { return err } defer out.Close() req, err := http.NewRequest("GET", url, nil) if err != nil { return err } req.Header.Set("User-Agent", UserAgent) resp, err := s.http.Do(req) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { return fmt.Errorf("invalid simplestreams source: got %d looking for %s", resp.StatusCode, path) } body := &TransferProgress{Reader: resp.Body, Length: resp.ContentLength, Handler: progress} sha256 := sha256.New() _, err = io.Copy(io.MultiWriter(out, sha256), body) if err != nil { return err } result := fmt.Sprintf("%x", sha256.Sum(nil)) if result != hash { os.Remove(target) return fmt.Errorf("Hash mismatch for %s: %s != %s", path, result, hash) } return nil } // Try http first if strings.HasPrefix(s.url, "https://") { err := download(fmt.Sprintf("http://%s/%s", strings.TrimPrefix(s.url, "https://"), path), hash, target) if err == nil { return nil } } err := download(fmt.Sprintf("%s/%s", s.url, path), hash, target) if err != nil { return err } return nil }
/* params: HTTP Verb Content-Encoding Content-Language Content-Length Content-MD5 Content-Type Date If-Modified-Since If-Match If-None-Match If-Unmodified-Since Range */ func (core Core) signature() string { signature := fmt.Sprintf("%s\n\n\n%s\n\n%s\n\n\n\n\n\n\n%s\n%s", strings.ToUpper(core.AzureRequest.Method), core.contentLength(), core.AzureRequest.Request.Header.Get("Content-Type"), core.canonicalizedHeaders(), core.canonicalizedResource()) decodedKey, _ := base64.StdEncoding.DecodeString(core.Credentials.AccessKey) sha256 := hmac.New(sha256.New, []byte(decodedKey)) sha256.Write([]byte(signature)) return base64.StdEncoding.EncodeToString(sha256.Sum(nil)) }
func (s *SimpleStreams) downloadFile(path string, hash string, target string, progress func(int)) error { download := func(url string, hash string, target string) error { out, err := os.Create(target) if err != nil { return err } defer out.Close() resp, err := s.http.Get(url) if err != nil { } defer resp.Body.Close() body := &TransferProgress{Reader: resp.Body, Length: resp.ContentLength, Handler: progress} sha256 := sha256.New() _, err = io.Copy(io.MultiWriter(out, sha256), body) if err != nil { return err } if fmt.Sprintf("%x", sha256.Sum(nil)) != hash { os.Remove(target) return fmt.Errorf("Hash mismatch") } return nil } // Try http first if strings.HasPrefix(s.url, "https://") { err := download(fmt.Sprintf("http://%s/%s", strings.TrimPrefix(s.url, "https://"), path), hash, target) if err == nil { return nil } } err := download(fmt.Sprintf("%s/%s", s.url, path), hash, target) if err != nil { return err } return nil }
// Calculate hashes // FROM: http://marcio.io/2015/07/calculating-multiple-file-hashes-in-a-single-pass/ func CalculateBasicHashes(filename string) (info models.HashInfo, err error) { rd, err := os.OpenFile(filename, os.O_RDONLY, 0) if err != nil { return } defer rd.Close() md5 := md5.New() sha1 := sha1.New() sha256 := sha256.New() sha512 := sha512.New() // For optimum speed, Getpagesize returns the underlying system's memory page size. pagesize := os.Getpagesize() // wraps the Reader object into a new buffered reader to read the files in chunks // and buffering them for performance. reader := bufio.NewReaderSize(rd, pagesize) // creates a multiplexer Writer object that will duplicate all write // operations when copying data from source into all different hashing algorithms // at the same time multiWriter := io.MultiWriter(md5, sha1, sha256, sha512) // Using a buffered reader, this will write to the writer multiplexer // so we only traverse through the file once, and can calculate all hashes // in a single byte buffered scan pass. // _, err = io.Copy(multiWriter, reader) if err != nil { return } info.Md5 = hex.EncodeToString(md5.Sum(nil)) info.Sha1 = hex.EncodeToString(sha1.Sum(nil)) info.Sha256 = hex.EncodeToString(sha256.Sum(nil)) info.Sha512 = hex.EncodeToString(sha512.Sum(nil)) return info, nil }
func getImgPostInfo(d *Daemon, r *http.Request, builddir string, post *os.File) (info shared.ImageInfo, err error) { var imageMeta *imageMetadata logger := logging.AddContext(shared.Log, log.Ctx{"function": "getImgPostInfo"}) public, _ := strconv.Atoi(r.Header.Get("X-LXD-public")) info.Public = public == 1 propHeaders := r.Header[http.CanonicalHeaderKey("X-LXD-properties")] ctype, ctypeParams, err := mime.ParseMediaType(r.Header.Get("Content-Type")) if err != nil { ctype = "application/octet-stream" } sha256 := sha256.New() var size int64 // Create a temporary file for the image tarball imageTarf, err := ioutil.TempFile(builddir, "lxd_tar_") if err != nil { return info, err } if ctype == "multipart/form-data" { // Parse the POST data post.Seek(0, 0) mr := multipart.NewReader(post, ctypeParams["boundary"]) // Get the metadata tarball part, err := mr.NextPart() if err != nil { return info, err } if part.FormName() != "metadata" { return info, fmt.Errorf("Invalid multipart image") } size, err = io.Copy(io.MultiWriter(imageTarf, sha256), part) info.Size += size imageTarf.Close() if err != nil { logger.Error( "Failed to copy the image tarfile", log.Ctx{"err": err}) return info, err } // Get the rootfs tarball part, err = mr.NextPart() if err != nil { logger.Error( "Failed to get the next part", log.Ctx{"err": err}) return info, err } if part.FormName() != "rootfs" { logger.Error( "Invalid multipart image") return info, fmt.Errorf("Invalid multipart image") } // Create a temporary file for the rootfs tarball rootfsTarf, err := ioutil.TempFile(builddir, "lxd_tar_") if err != nil { return info, err } size, err = io.Copy(io.MultiWriter(rootfsTarf, sha256), part) info.Size += size rootfsTarf.Close() if err != nil { logger.Error( "Failed to copy the rootfs tarfile", log.Ctx{"err": err}) return info, err } info.Filename = part.FileName() info.Fingerprint = fmt.Sprintf("%x", sha256.Sum(nil)) expectedFingerprint := r.Header.Get("X-LXD-fingerprint") if expectedFingerprint != "" && info.Fingerprint != expectedFingerprint { err = fmt.Errorf("fingerprints don't match, got %s expected %s", info.Fingerprint, expectedFingerprint) return info, err } imgfname := shared.VarPath("images", info.Fingerprint) err = shared.FileMove(imageTarf.Name(), imgfname) if err != nil { logger.Error( "Failed to move the image tarfile", log.Ctx{ "err": err, "source": imageTarf.Name(), "dest": imgfname}) return info, err } rootfsfname := shared.VarPath("images", info.Fingerprint+".rootfs") err = shared.FileMove(rootfsTarf.Name(), rootfsfname) if err != nil { logger.Error( "Failed to move the rootfs tarfile", log.Ctx{ "err": err, "source": rootfsTarf.Name(), "dest": imgfname}) return info, err } imageMeta, err = getImageMetadata(imgfname) if err != nil { logger.Error( "Failed to get image metadata", log.Ctx{"err": err}) return info, err } } else { post.Seek(0, 0) size, err = io.Copy(io.MultiWriter(imageTarf, sha256), post) info.Size = size imageTarf.Close() logger.Debug("Tar size", log.Ctx{"size": size}) if err != nil { logger.Error( "Failed to copy the tarfile", log.Ctx{"err": err}) return info, err } info.Filename = r.Header.Get("X-LXD-filename") info.Fingerprint = fmt.Sprintf("%x", sha256.Sum(nil)) expectedFingerprint := r.Header.Get("X-LXD-fingerprint") if expectedFingerprint != "" && info.Fingerprint != expectedFingerprint { logger.Error( "Fingerprints don't match", log.Ctx{ "got": info.Fingerprint, "expected": expectedFingerprint}) err = fmt.Errorf( "fingerprints don't match, got %s expected %s", info.Fingerprint, expectedFingerprint) return info, err } imgfname := shared.VarPath("images", info.Fingerprint) err = shared.FileMove(imageTarf.Name(), imgfname) if err != nil { logger.Error( "Failed to move the tarfile", log.Ctx{ "err": err, "source": imageTarf.Name(), "dest": imgfname}) return info, err } imageMeta, err = getImageMetadata(imgfname) if err != nil { logger.Error( "Failed to get image metadata", log.Ctx{"err": err}) return info, err } } info.Architecture, _ = shared.ArchitectureId(imageMeta.Architecture) info.CreationDate = imageMeta.CreationDate info.ExpiryDate = imageMeta.ExpiryDate info.Properties = imageMeta.Properties if len(propHeaders) > 0 { for _, ph := range propHeaders { p, _ := url.ParseQuery(ph) for pkey, pval := range p { info.Properties[pkey] = pval[0] } } } return info, nil }
/* * This function takes a container or snapshot from the local image server and * exports it as an image. */ func imgPostContInfo(d *Daemon, r *http.Request, req imagePostReq, builddir string) (info shared.ImageInfo, err error) { info.Properties = map[string]string{} name := req.Source["name"] ctype := req.Source["type"] if ctype == "" || name == "" { return info, fmt.Errorf("No source provided") } switch ctype { case "snapshot": if !shared.IsSnapshot(name) { return info, fmt.Errorf("Not a snapshot") } case "container": if shared.IsSnapshot(name) { return info, fmt.Errorf("This is a snapshot") } default: return info, fmt.Errorf("Bad type") } info.Filename = req.Filename switch req.Public { case true: info.Public = true case false: info.Public = false } c, err := containerLoadByName(d, name) if err != nil { return info, err } // Build the actual image file tarfile, err := ioutil.TempFile(builddir, "lxd_build_tar_") if err != nil { return info, err } defer os.Remove(tarfile.Name()) if err := c.Export(tarfile); err != nil { tarfile.Close() return info, fmt.Errorf("imgPostContInfo: export failed: %s", err) } tarfile.Close() compress, err := d.ConfigValueGet("images.compression_algorithm") if err != nil { return info, err } // Default to gzip for this if compress == "" { compress = "gzip" } var compressedPath string if compress != "none" { compressedPath, err = compressFile(tarfile.Name(), compress) if err != nil { return info, err } } else { compressedPath = tarfile.Name() } defer os.Remove(compressedPath) sha256 := sha256.New() tarf, err := os.Open(compressedPath) if err != nil { return info, err } info.Size, err = io.Copy(sha256, tarf) tarf.Close() if err != nil { return info, err } info.Fingerprint = fmt.Sprintf("%x", sha256.Sum(nil)) _, err = dbImageGet(d.db, info.Fingerprint, false, true) if err == nil { return info, fmt.Errorf("The image already exists: %s", info.Fingerprint) } /* rename the the file to the expected name so our caller can use it */ finalName := shared.VarPath("images", info.Fingerprint) err = shared.FileMove(compressedPath, finalName) if err != nil { return info, err } info.Architecture = c.Architecture() info.Properties = req.Properties return info, nil }
func getImgPostInfo(d *Daemon, r *http.Request, builddir string) (public int, fingerprint string, arch int, filename string, size int64, properties map[string]string, err error) { // Is this a container request? decoder := json.NewDecoder(r.Body) req := imageFromContainerPostReq{} if err = decoder.Decode(&req); err == nil { return imgPostContInfo(d, r, req, builddir) } // ok we've got an image in the body public, _ = strconv.Atoi(r.Header.Get("X-LXD-public")) filename = r.Header.Get("X-LXD-filename") propHeaders := r.Header[http.CanonicalHeaderKey("X-LXD-properties")] properties = map[string]string{} if len(propHeaders) > 0 { for _, ph := range propHeaders { p, _ := url.ParseQuery(ph) for pkey, pval := range p { properties[pkey] = pval[0] } } } // Create a file for the tarball tarf, err := ioutil.TempFile(builddir, "lxd_tar_") if err != nil { return 0, "", 0, "", 0, properties, err } tarfname := tarf.Name() sha256 := sha256.New() var size1, size2 int64 size1, err = io.Copy(io.MultiWriter(tarf, sha256), decoder.Buffered()) if err == nil { size2, err = io.Copy(io.MultiWriter(tarf, sha256), r.Body) } size = size1 + size2 tarf.Close() if err != nil { return 0, "", 0, "", 0, properties, err } fingerprint = fmt.Sprintf("%x", sha256.Sum(nil)) expectedFingerprint := r.Header.Get("X-LXD-fingerprint") if expectedFingerprint != "" && fingerprint != expectedFingerprint { err = fmt.Errorf("fingerprints don't match, got %s expected %s", fingerprint, expectedFingerprint) return 0, "", 0, "", 0, properties, err } imagefname := filepath.Join(builddir, fingerprint) err = os.Rename(tarfname, imagefname) if err != nil { return 0, "", 0, "", 0, properties, err } var imageMeta *imageMetadata imageMeta, err = getImageMetadata(imagefname) if err != nil { return 0, "", 0, "", 0, properties, err } arch, _ = shared.ArchitectureId(imageMeta.Architecture) err = nil return }
/* * This function takes a container or snapshot from the local image server and * exports it as an image. */ func imgPostContInfo(d *Daemon, r *http.Request, req imageFromContainerPostReq, builddir string) (public int, fingerprint string, arch int, filename string, size int64, properties map[string]string, err error) { properties = map[string]string{} name := req.Source["name"] ctype := req.Source["type"] if ctype == "" || name == "" { return 0, "", 0, "", 0, properties, fmt.Errorf("No source provided") } switch ctype { case "snapshot": if !shared.IsSnapshot(name) { return 0, "", 0, "", 0, properties, fmt.Errorf("Not a snapshot") } case "container": if shared.IsSnapshot(name) { return 0, "", 0, "", 0, properties, fmt.Errorf("This is a snapshot") } default: return 0, "", 0, "", 0, properties, fmt.Errorf("Bad type") } filename = req.Filename switch req.Public { case true: public = 1 case false: public = 0 } snap := "" if ctype == "snapshot" { fields := strings.SplitN(name, "/", 2) if len(fields) != 2 { return 0, "", 0, "", 0, properties, fmt.Errorf("Not a snapshot") } name = fields[0] snap = fields[1] } c, err := newLxdContainer(name, d) if err != nil { return 0, "", 0, "", 0, properties, err } if err := c.exportToDir(snap, builddir); err != nil { return 0, "", 0, "", 0, properties, err } // Build the actual image file tarfname := fmt.Sprintf("%s.tar.xz", name) tarpath := filepath.Join(builddir, tarfname) args := []string{"-C", builddir, "--numeric-owner", "-Jcf", tarpath} if shared.PathExists(filepath.Join(builddir, "metadata.yaml")) { args = append(args, "metadata.yaml") } args = append(args, "rootfs") output, err := exec.Command("tar", args...).CombinedOutput() if err != nil { shared.Debugf("image packing failed\n") shared.Debugf("command was: tar %q\n", args) shared.Debugf(string(output)) return 0, "", 0, "", 0, properties, err } // get the size and fingerprint sha256 := sha256.New() tarf, err := os.Open(tarpath) if err != nil { return 0, "", 0, "", 0, properties, err } size, err = io.Copy(sha256, tarf) tarf.Close() if err != nil { return 0, "", 0, "", 0, properties, err } fingerprint = fmt.Sprintf("%x", sha256.Sum(nil)) /* rename the the file to the expected name so our caller can use it */ imagefname := filepath.Join(builddir, fingerprint) err = os.Rename(tarpath, imagefname) if err != nil { return 0, "", 0, "", 0, properties, err } arch = c.architecture properties = req.Properties return }
/* * This function takes a container or snapshot from the local image server and * exports it as an image. */ func imgPostContInfo(d *Daemon, r *http.Request, req imagePostReq, builddir string) (info shared.ImageInfo, err error) { info.Properties = map[string]string{} name := req.Source["name"] ctype := req.Source["type"] if ctype == "" || name == "" { return info, fmt.Errorf("No source provided") } switch ctype { case "snapshot": if !shared.IsSnapshot(name) { return info, fmt.Errorf("Not a snapshot") } case "container": if shared.IsSnapshot(name) { return info, fmt.Errorf("This is a snapshot") } default: return info, fmt.Errorf("Bad type") } info.Filename = req.Filename switch req.Public { case true: info.Public = 1 case false: info.Public = 0 } snap := "" if ctype == "snapshot" { fields := strings.SplitN(name, "/", 2) if len(fields) != 2 { return info, fmt.Errorf("Not a snapshot") } name = fields[0] snap = fields[1] } c, err := newLxdContainer(name, d) if err != nil { return info, err } // Build the actual image file tarfile, err := ioutil.TempFile(builddir, "lxd_build_tar_") if err != nil { return info, err } if err := c.exportToTar(snap, tarfile); err != nil { tarfile.Close() return info, fmt.Errorf("imgPostContInfo: exportToTar failed: %s\n", err) } tarfile.Close() _, err = exec.Command("gzip", tarfile.Name()).CombinedOutput() if err != nil { shared.Debugf("image compression\n") return info, err } gztarpath := fmt.Sprintf("%s.gz", tarfile.Name()) sha256 := sha256.New() tarf, err := os.Open(gztarpath) if err != nil { return info, err } info.Size, err = io.Copy(sha256, tarf) tarf.Close() if err != nil { return info, err } info.Fingerprint = fmt.Sprintf("%x", sha256.Sum(nil)) /* rename the the file to the expected name so our caller can use it */ finalName := shared.VarPath("images", info.Fingerprint) err = shared.FileMove(gztarpath, finalName) if err != nil { return info, err } info.Architecture = c.architecture info.Properties = req.Properties return info, nil }
func getImgPostInfo(d *Daemon, r *http.Request, builddir string) (info shared.ImageInfo, err error) { var imageMeta *imageMetadata // Store the post data to disk post, err := ioutil.TempFile(builddir, "lxd_post_") if err != nil { return info, err } defer os.Remove(post.Name()) _, err = io.Copy(post, r.Body) if err != nil { return info, err } // Is this a container request? post.Seek(0, 0) decoder := json.NewDecoder(post) req := imageFromContainerPostReq{} if err = decoder.Decode(&req); err == nil { return imgPostContInfo(d, r, req, builddir) } // ok we've got an image in the body info.Public, _ = strconv.Atoi(r.Header.Get("X-LXD-public")) propHeaders := r.Header[http.CanonicalHeaderKey("X-LXD-properties")] ctype, ctypeParams, err := mime.ParseMediaType(r.Header.Get("Content-Type")) if err != nil { ctype = "application/octet-stream" } sha256 := sha256.New() var size int64 // Create a temporary file for the image tarball imageTarf, err := ioutil.TempFile(builddir, "lxd_tar_") if err != nil { return info, err } if ctype == "multipart/form-data" { // Create a temporary file for the rootfs tarball rootfsTarf, err := ioutil.TempFile(builddir, "lxd_tar_") if err != nil { return info, err } // Parse the POST data post.Seek(0, 0) mr := multipart.NewReader(post, ctypeParams["boundary"]) // Get the metadata tarball part, err := mr.NextPart() if err != nil { return info, err } if part.FormName() != "metadata" { return info, fmt.Errorf("Invalid multipart image") } size, err = io.Copy(io.MultiWriter(imageTarf, sha256), part) info.Size += size imageTarf.Close() if err != nil { return info, err } // Get the rootfs tarball part, err = mr.NextPart() if err != nil { return info, err } if part.FormName() != "rootfs" { return info, fmt.Errorf("Invalid multipart image") } size, err = io.Copy(io.MultiWriter(rootfsTarf, sha256), part) info.Size += size rootfsTarf.Close() if err != nil { return info, err } info.Filename = part.FileName() info.Fingerprint = fmt.Sprintf("%x", sha256.Sum(nil)) expectedFingerprint := r.Header.Get("X-LXD-fingerprint") if expectedFingerprint != "" && info.Fingerprint != expectedFingerprint { err = fmt.Errorf("fingerprints don't match, got %s expected %s", info.Fingerprint, expectedFingerprint) return info, err } imgfname := filepath.Join(builddir, info.Fingerprint) err = os.Rename(imageTarf.Name(), imgfname) if err != nil { return info, err } rootfsfname := filepath.Join(builddir, info.Fingerprint+".rootfs") err = os.Rename(rootfsTarf.Name(), rootfsfname) if err != nil { return info, err } imageMeta, err = getImageMetadata(imgfname) if err != nil { return info, err } } else { post.Seek(0, 0) size, err = io.Copy(io.MultiWriter(imageTarf, sha256), post) info.Size = size imageTarf.Close() if err != nil { return info, err } info.Filename = r.Header.Get("X-LXD-filename") info.Fingerprint = fmt.Sprintf("%x", sha256.Sum(nil)) expectedFingerprint := r.Header.Get("X-LXD-fingerprint") if expectedFingerprint != "" && info.Fingerprint != expectedFingerprint { err = fmt.Errorf("fingerprints don't match, got %s expected %s", info.Fingerprint, expectedFingerprint) return info, err } imgfname := filepath.Join(builddir, info.Fingerprint) err = os.Rename(imageTarf.Name(), imgfname) if err != nil { return info, err } imageMeta, err = getImageMetadata(imgfname) if err != nil { return info, err } } info.Architecture, _ = shared.ArchitectureId(imageMeta.Architecture) info.CreationDate = imageMeta.CreationDate info.ExpiryDate = imageMeta.ExpiryDate info.Properties = imageMeta.Properties if len(propHeaders) > 0 { for _, ph := range propHeaders { p, _ := url.ParseQuery(ph) for pkey, pval := range p { info.Properties[pkey] = pval[0] } } } return info, nil }
// computes hexified hash over bytes from a Reader // ... this is one place where I really miss exceptions func computeHash(rdr io.Reader) string { sha256 := sha256.New() io.Copy(sha256, rdr) hash := sha256.Sum(make([]byte, 0)) return hex.EncodeToString(hash) }